41014 lines
1.1 MiB
41014 lines
1.1 MiB
//
|
|
// 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.
|
|
//
|
|
|
|
// THIS CODE IS GENERATED - DO NOT MODIFY!
|
|
|
|
#include "trunks/tpm_generated.h"
|
|
|
|
#include <string>
|
|
|
|
#include <base/bind.h>
|
|
#include <base/callback.h>
|
|
#include <base/logging.h>
|
|
#include <base/macros.h>
|
|
#include <base/stl_util.h>
|
|
#include <base/strings/string_number_conversions.h>
|
|
#include <base/sys_byteorder.h>
|
|
#include <crypto/secure_hash.h>
|
|
|
|
#include "trunks/authorization_delegate.h"
|
|
#include "trunks/command_transceiver.h"
|
|
#include "trunks/error_codes.h"
|
|
|
|
|
|
namespace trunks {
|
|
|
|
size_t GetNumberOfRequestHandles(TPM_CC command_code) {
|
|
switch (command_code) {
|
|
case TPM_CC_Startup: return 0;
|
|
case TPM_CC_Shutdown: return 0;
|
|
case TPM_CC_SelfTest: return 0;
|
|
case TPM_CC_IncrementalSelfTest: return 0;
|
|
case TPM_CC_GetTestResult: return 0;
|
|
case TPM_CC_StartAuthSession: return 2;
|
|
case TPM_CC_PolicyRestart: return 1;
|
|
case TPM_CC_Create: return 1;
|
|
case TPM_CC_Load: return 1;
|
|
case TPM_CC_LoadExternal: return 0;
|
|
case TPM_CC_ReadPublic: return 1;
|
|
case TPM_CC_ActivateCredential: return 2;
|
|
case TPM_CC_MakeCredential: return 1;
|
|
case TPM_CC_Unseal: return 1;
|
|
case TPM_CC_ObjectChangeAuth: return 2;
|
|
case TPM_CC_Duplicate: return 2;
|
|
case TPM_CC_Rewrap: return 2;
|
|
case TPM_CC_Import: return 1;
|
|
case TPM_CC_RSA_Encrypt: return 1;
|
|
case TPM_CC_RSA_Decrypt: return 1;
|
|
case TPM_CC_ECDH_KeyGen: return 1;
|
|
case TPM_CC_ECDH_ZGen: return 1;
|
|
case TPM_CC_ECC_Parameters: return 0;
|
|
case TPM_CC_ZGen_2Phase: return 1;
|
|
case TPM_CC_EncryptDecrypt: return 1;
|
|
case TPM_CC_Hash: return 0;
|
|
case TPM_CC_HMAC: return 1;
|
|
case TPM_CC_GetRandom: return 0;
|
|
case TPM_CC_StirRandom: return 0;
|
|
case TPM_CC_HMAC_Start: return 1;
|
|
case TPM_CC_HashSequenceStart: return 0;
|
|
case TPM_CC_SequenceUpdate: return 1;
|
|
case TPM_CC_SequenceComplete: return 1;
|
|
case TPM_CC_EventSequenceComplete: return 2;
|
|
case TPM_CC_Certify: return 2;
|
|
case TPM_CC_CertifyCreation: return 2;
|
|
case TPM_CC_Quote: return 1;
|
|
case TPM_CC_GetSessionAuditDigest: return 3;
|
|
case TPM_CC_GetCommandAuditDigest: return 2;
|
|
case TPM_CC_GetTime: return 2;
|
|
case TPM_CC_Commit: return 1;
|
|
case TPM_CC_EC_Ephemeral: return 0;
|
|
case TPM_CC_VerifySignature: return 1;
|
|
case TPM_CC_Sign: return 1;
|
|
case TPM_CC_SetCommandCodeAuditStatus: return 1;
|
|
case TPM_CC_PCR_Extend: return 1;
|
|
case TPM_CC_PCR_Event: return 1;
|
|
case TPM_CC_PCR_Read: return 0;
|
|
case TPM_CC_PCR_Allocate: return 1;
|
|
case TPM_CC_PCR_SetAuthPolicy: return 2;
|
|
case TPM_CC_PCR_SetAuthValue: return 1;
|
|
case TPM_CC_PCR_Reset: return 1;
|
|
case TPM_CC_PolicySigned: return 2;
|
|
case TPM_CC_PolicySecret: return 2;
|
|
case TPM_CC_PolicyTicket: return 1;
|
|
case TPM_CC_PolicyOR: return 1;
|
|
case TPM_CC_PolicyPCR: return 1;
|
|
case TPM_CC_PolicyLocality: return 1;
|
|
case TPM_CC_PolicyNV: return 3;
|
|
case TPM_CC_PolicyCounterTimer: return 1;
|
|
case TPM_CC_PolicyCommandCode: return 1;
|
|
case TPM_CC_PolicyPhysicalPresence: return 1;
|
|
case TPM_CC_PolicyCpHash: return 1;
|
|
case TPM_CC_PolicyNameHash: return 1;
|
|
case TPM_CC_PolicyDuplicationSelect: return 1;
|
|
case TPM_CC_PolicyAuthorize: return 1;
|
|
case TPM_CC_PolicyAuthValue: return 1;
|
|
case TPM_CC_PolicyPassword: return 1;
|
|
case TPM_CC_PolicyGetDigest: return 1;
|
|
case TPM_CC_PolicyNvWritten: return 1;
|
|
case TPM_CC_CreatePrimary: return 1;
|
|
case TPM_CC_HierarchyControl: return 1;
|
|
case TPM_CC_SetPrimaryPolicy: return 1;
|
|
case TPM_CC_ChangePPS: return 1;
|
|
case TPM_CC_ChangeEPS: return 1;
|
|
case TPM_CC_Clear: return 1;
|
|
case TPM_CC_ClearControl: return 1;
|
|
case TPM_CC_HierarchyChangeAuth: return 1;
|
|
case TPM_CC_DictionaryAttackLockReset: return 1;
|
|
case TPM_CC_DictionaryAttackParameters: return 1;
|
|
case TPM_CC_PP_Commands: return 1;
|
|
case TPM_CC_SetAlgorithmSet: return 1;
|
|
case TPM_CC_FieldUpgradeStart: return 2;
|
|
case TPM_CC_FieldUpgradeData: return 0;
|
|
case TPM_CC_FirmwareRead: return 0;
|
|
case TPM_CC_ContextSave: return 1;
|
|
case TPM_CC_ContextLoad: return 0;
|
|
case TPM_CC_FlushContext: return 0;
|
|
case TPM_CC_EvictControl: return 2;
|
|
case TPM_CC_ReadClock: return 0;
|
|
case TPM_CC_ClockSet: return 1;
|
|
case TPM_CC_ClockRateAdjust: return 1;
|
|
case TPM_CC_GetCapability: return 0;
|
|
case TPM_CC_TestParms: return 0;
|
|
case TPM_CC_NV_DefineSpace: return 1;
|
|
case TPM_CC_NV_UndefineSpace: return 2;
|
|
case TPM_CC_NV_UndefineSpaceSpecial: return 2;
|
|
case TPM_CC_NV_ReadPublic: return 1;
|
|
case TPM_CC_NV_Write: return 2;
|
|
case TPM_CC_NV_Increment: return 2;
|
|
case TPM_CC_NV_Extend: return 2;
|
|
case TPM_CC_NV_SetBits: return 2;
|
|
case TPM_CC_NV_WriteLock: return 2;
|
|
case TPM_CC_NV_GlobalWriteLock: return 1;
|
|
case TPM_CC_NV_Read: return 2;
|
|
case TPM_CC_NV_ReadLock: return 2;
|
|
case TPM_CC_NV_ChangeAuth: return 1;
|
|
case TPM_CC_NV_Certify: return 3;
|
|
default: LOG(WARNING) << "Unknown command code: " << command_code;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
size_t GetNumberOfResponseHandles(TPM_CC command_code) {
|
|
switch (command_code) {
|
|
case TPM_CC_Startup: return 0;
|
|
case TPM_CC_Shutdown: return 0;
|
|
case TPM_CC_SelfTest: return 0;
|
|
case TPM_CC_IncrementalSelfTest: return 0;
|
|
case TPM_CC_GetTestResult: return 0;
|
|
case TPM_CC_StartAuthSession: return 1;
|
|
case TPM_CC_PolicyRestart: return 0;
|
|
case TPM_CC_Create: return 0;
|
|
case TPM_CC_Load: return 1;
|
|
case TPM_CC_LoadExternal: return 1;
|
|
case TPM_CC_ReadPublic: return 0;
|
|
case TPM_CC_ActivateCredential: return 0;
|
|
case TPM_CC_MakeCredential: return 0;
|
|
case TPM_CC_Unseal: return 0;
|
|
case TPM_CC_ObjectChangeAuth: return 0;
|
|
case TPM_CC_Duplicate: return 0;
|
|
case TPM_CC_Rewrap: return 0;
|
|
case TPM_CC_Import: return 0;
|
|
case TPM_CC_RSA_Encrypt: return 0;
|
|
case TPM_CC_RSA_Decrypt: return 0;
|
|
case TPM_CC_ECDH_KeyGen: return 0;
|
|
case TPM_CC_ECDH_ZGen: return 0;
|
|
case TPM_CC_ECC_Parameters: return 0;
|
|
case TPM_CC_ZGen_2Phase: return 0;
|
|
case TPM_CC_EncryptDecrypt: return 0;
|
|
case TPM_CC_Hash: return 0;
|
|
case TPM_CC_HMAC: return 0;
|
|
case TPM_CC_GetRandom: return 0;
|
|
case TPM_CC_StirRandom: return 0;
|
|
case TPM_CC_HMAC_Start: return 1;
|
|
case TPM_CC_HashSequenceStart: return 1;
|
|
case TPM_CC_SequenceUpdate: return 0;
|
|
case TPM_CC_SequenceComplete: return 0;
|
|
case TPM_CC_EventSequenceComplete: return 0;
|
|
case TPM_CC_Certify: return 0;
|
|
case TPM_CC_CertifyCreation: return 0;
|
|
case TPM_CC_Quote: return 0;
|
|
case TPM_CC_GetSessionAuditDigest: return 0;
|
|
case TPM_CC_GetCommandAuditDigest: return 0;
|
|
case TPM_CC_GetTime: return 0;
|
|
case TPM_CC_Commit: return 0;
|
|
case TPM_CC_EC_Ephemeral: return 0;
|
|
case TPM_CC_VerifySignature: return 0;
|
|
case TPM_CC_Sign: return 0;
|
|
case TPM_CC_SetCommandCodeAuditStatus: return 0;
|
|
case TPM_CC_PCR_Extend: return 0;
|
|
case TPM_CC_PCR_Event: return 0;
|
|
case TPM_CC_PCR_Read: return 0;
|
|
case TPM_CC_PCR_Allocate: return 0;
|
|
case TPM_CC_PCR_SetAuthPolicy: return 0;
|
|
case TPM_CC_PCR_SetAuthValue: return 0;
|
|
case TPM_CC_PCR_Reset: return 0;
|
|
case TPM_CC_PolicySigned: return 0;
|
|
case TPM_CC_PolicySecret: return 0;
|
|
case TPM_CC_PolicyTicket: return 0;
|
|
case TPM_CC_PolicyOR: return 0;
|
|
case TPM_CC_PolicyPCR: return 0;
|
|
case TPM_CC_PolicyLocality: return 0;
|
|
case TPM_CC_PolicyNV: return 0;
|
|
case TPM_CC_PolicyCounterTimer: return 0;
|
|
case TPM_CC_PolicyCommandCode: return 0;
|
|
case TPM_CC_PolicyPhysicalPresence: return 0;
|
|
case TPM_CC_PolicyCpHash: return 0;
|
|
case TPM_CC_PolicyNameHash: return 0;
|
|
case TPM_CC_PolicyDuplicationSelect: return 0;
|
|
case TPM_CC_PolicyAuthorize: return 0;
|
|
case TPM_CC_PolicyAuthValue: return 0;
|
|
case TPM_CC_PolicyPassword: return 0;
|
|
case TPM_CC_PolicyGetDigest: return 0;
|
|
case TPM_CC_PolicyNvWritten: return 0;
|
|
case TPM_CC_CreatePrimary: return 1;
|
|
case TPM_CC_HierarchyControl: return 0;
|
|
case TPM_CC_SetPrimaryPolicy: return 0;
|
|
case TPM_CC_ChangePPS: return 0;
|
|
case TPM_CC_ChangeEPS: return 0;
|
|
case TPM_CC_Clear: return 0;
|
|
case TPM_CC_ClearControl: return 0;
|
|
case TPM_CC_HierarchyChangeAuth: return 0;
|
|
case TPM_CC_DictionaryAttackLockReset: return 0;
|
|
case TPM_CC_DictionaryAttackParameters: return 0;
|
|
case TPM_CC_PP_Commands: return 0;
|
|
case TPM_CC_SetAlgorithmSet: return 0;
|
|
case TPM_CC_FieldUpgradeStart: return 0;
|
|
case TPM_CC_FieldUpgradeData: return 0;
|
|
case TPM_CC_FirmwareRead: return 0;
|
|
case TPM_CC_ContextSave: return 0;
|
|
case TPM_CC_ContextLoad: return 1;
|
|
case TPM_CC_FlushContext: return 0;
|
|
case TPM_CC_EvictControl: return 0;
|
|
case TPM_CC_ReadClock: return 0;
|
|
case TPM_CC_ClockSet: return 0;
|
|
case TPM_CC_ClockRateAdjust: return 0;
|
|
case TPM_CC_GetCapability: return 0;
|
|
case TPM_CC_TestParms: return 0;
|
|
case TPM_CC_NV_DefineSpace: return 0;
|
|
case TPM_CC_NV_UndefineSpace: return 0;
|
|
case TPM_CC_NV_UndefineSpaceSpecial: return 0;
|
|
case TPM_CC_NV_ReadPublic: return 0;
|
|
case TPM_CC_NV_Write: return 0;
|
|
case TPM_CC_NV_Increment: return 0;
|
|
case TPM_CC_NV_Extend: return 0;
|
|
case TPM_CC_NV_SetBits: return 0;
|
|
case TPM_CC_NV_WriteLock: return 0;
|
|
case TPM_CC_NV_GlobalWriteLock: return 0;
|
|
case TPM_CC_NV_Read: return 0;
|
|
case TPM_CC_NV_ReadLock: return 0;
|
|
case TPM_CC_NV_ChangeAuth: return 0;
|
|
case TPM_CC_NV_Certify: return 0;
|
|
default: LOG(WARNING) << "Unknown command code: " << command_code;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
TPM_RC Serialize_uint8_t(const uint8_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
uint8_t value_net = value;
|
|
switch (sizeof(uint8_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(uint8_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_uint8_t(
|
|
std::string* buffer,
|
|
uint8_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(uint8_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
uint8_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(uint8_t));
|
|
switch (sizeof(uint8_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(uint8_t)));
|
|
}
|
|
buffer->erase(0, sizeof(uint8_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_int8_t(const int8_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
int8_t value_net = value;
|
|
switch (sizeof(int8_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(int8_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_int8_t(
|
|
std::string* buffer,
|
|
int8_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(int8_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
int8_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(int8_t));
|
|
switch (sizeof(int8_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(int8_t)));
|
|
}
|
|
buffer->erase(0, sizeof(int8_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_int(const int& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
int value_net = value;
|
|
switch (sizeof(int)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(int));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_int(
|
|
std::string* buffer,
|
|
int* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(int))
|
|
return TPM_RC_INSUFFICIENT;
|
|
int value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(int));
|
|
switch (sizeof(int)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(int)));
|
|
}
|
|
buffer->erase(0, sizeof(int));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_uint16_t(const uint16_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
uint16_t value_net = value;
|
|
switch (sizeof(uint16_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(uint16_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_uint16_t(
|
|
std::string* buffer,
|
|
uint16_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(uint16_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
uint16_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(uint16_t));
|
|
switch (sizeof(uint16_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(uint16_t)));
|
|
}
|
|
buffer->erase(0, sizeof(uint16_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_int16_t(const int16_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
int16_t value_net = value;
|
|
switch (sizeof(int16_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(int16_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_int16_t(
|
|
std::string* buffer,
|
|
int16_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(int16_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
int16_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(int16_t));
|
|
switch (sizeof(int16_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(int16_t)));
|
|
}
|
|
buffer->erase(0, sizeof(int16_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_uint32_t(const uint32_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
uint32_t value_net = value;
|
|
switch (sizeof(uint32_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(uint32_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_uint32_t(
|
|
std::string* buffer,
|
|
uint32_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(uint32_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
uint32_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(uint32_t));
|
|
switch (sizeof(uint32_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(uint32_t)));
|
|
}
|
|
buffer->erase(0, sizeof(uint32_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_int32_t(const int32_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
int32_t value_net = value;
|
|
switch (sizeof(int32_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(int32_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_int32_t(
|
|
std::string* buffer,
|
|
int32_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(int32_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
int32_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(int32_t));
|
|
switch (sizeof(int32_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(int32_t)));
|
|
}
|
|
buffer->erase(0, sizeof(int32_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_uint64_t(const uint64_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
uint64_t value_net = value;
|
|
switch (sizeof(uint64_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(uint64_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_uint64_t(
|
|
std::string* buffer,
|
|
uint64_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(uint64_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
uint64_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(uint64_t));
|
|
switch (sizeof(uint64_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(uint64_t)));
|
|
}
|
|
buffer->erase(0, sizeof(uint64_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_int64_t(const int64_t& value, std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
int64_t value_net = value;
|
|
switch (sizeof(int64_t)) {
|
|
case 2:
|
|
value_net = base::HostToNet16(value);
|
|
break;
|
|
case 4:
|
|
value_net = base::HostToNet32(value);
|
|
break;
|
|
case 8:
|
|
value_net = base::HostToNet64(value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char* value_bytes = reinterpret_cast<const char*>(&value_net);
|
|
buffer->append(value_bytes, sizeof(int64_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Parse_int64_t(
|
|
std::string* buffer,
|
|
int64_t* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
if (buffer->size() < sizeof(int64_t))
|
|
return TPM_RC_INSUFFICIENT;
|
|
int64_t value_net = 0;
|
|
memcpy(&value_net, buffer->data(), sizeof(int64_t));
|
|
switch (sizeof(int64_t)) {
|
|
case 2:
|
|
*value = base::NetToHost16(value_net);
|
|
break;
|
|
case 4:
|
|
*value = base::NetToHost32(value_net);
|
|
break;
|
|
case 8:
|
|
*value = base::NetToHost64(value_net);
|
|
break;
|
|
default:
|
|
*value = value_net;
|
|
}
|
|
if (value_bytes) {
|
|
value_bytes->append(buffer->substr(0, sizeof(int64_t)));
|
|
}
|
|
buffer->erase(0, sizeof(int64_t));
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Serialize_UINT8(
|
|
const UINT8& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_uint8_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_UINT8(
|
|
std::string* buffer,
|
|
UINT8* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_uint8_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_BYTE(
|
|
const BYTE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_uint8_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_BYTE(
|
|
std::string* buffer,
|
|
BYTE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_uint8_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_INT8(
|
|
const INT8& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_int8_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_INT8(
|
|
std::string* buffer,
|
|
INT8* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_int8_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_BOOL(
|
|
const BOOL& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_int(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_BOOL(
|
|
std::string* buffer,
|
|
BOOL* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_int(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_UINT16(
|
|
const UINT16& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_uint16_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_UINT16(
|
|
std::string* buffer,
|
|
UINT16* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_uint16_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_INT16(
|
|
const INT16& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_int16_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_INT16(
|
|
std::string* buffer,
|
|
INT16* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_int16_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_UINT32(
|
|
const UINT32& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_uint32_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_UINT32(
|
|
std::string* buffer,
|
|
UINT32* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_uint32_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_INT32(
|
|
const INT32& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_int32_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_INT32(
|
|
std::string* buffer,
|
|
INT32* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_int32_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_UINT64(
|
|
const UINT64& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_uint64_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_UINT64(
|
|
std::string* buffer,
|
|
UINT64* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_uint64_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_INT64(
|
|
const INT64& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_int64_t(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_INT64(
|
|
std::string* buffer,
|
|
INT64* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_int64_t(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_ALGORITHM_ID(
|
|
const TPM_ALGORITHM_ID& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_ALGORITHM_ID(
|
|
std::string* buffer,
|
|
TPM_ALGORITHM_ID* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_MODIFIER_INDICATOR(
|
|
const TPM_MODIFIER_INDICATOR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_MODIFIER_INDICATOR(
|
|
std::string* buffer,
|
|
TPM_MODIFIER_INDICATOR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_AUTHORIZATION_SIZE(
|
|
const TPM_AUTHORIZATION_SIZE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_AUTHORIZATION_SIZE(
|
|
std::string* buffer,
|
|
TPM_AUTHORIZATION_SIZE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_PARAMETER_SIZE(
|
|
const TPM_PARAMETER_SIZE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_PARAMETER_SIZE(
|
|
std::string* buffer,
|
|
TPM_PARAMETER_SIZE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_KEY_SIZE(
|
|
const TPM_KEY_SIZE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_KEY_SIZE(
|
|
std::string* buffer,
|
|
TPM_KEY_SIZE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_KEY_BITS(
|
|
const TPM_KEY_BITS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_KEY_BITS(
|
|
std::string* buffer,
|
|
TPM_KEY_BITS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_HANDLE(
|
|
const TPM_HANDLE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_HANDLE(
|
|
std::string* buffer,
|
|
TPM_HANDLE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_DIGEST(
|
|
const TPM2B_DIGEST& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_DIGEST(
|
|
std::string* buffer,
|
|
TPM2B_DIGEST* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_DIGEST Make_TPM2B_DIGEST(
|
|
const std::string& bytes) {
|
|
TPM2B_DIGEST tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_DIGEST));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_DIGEST(
|
|
const TPM2B_DIGEST& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_NONCE(
|
|
const TPM2B_NONCE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM2B_DIGEST(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_NONCE(
|
|
std::string* buffer,
|
|
TPM2B_NONCE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_AUTH(
|
|
const TPM2B_AUTH& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM2B_DIGEST(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_AUTH(
|
|
std::string* buffer,
|
|
TPM2B_AUTH* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_OPERAND(
|
|
const TPM2B_OPERAND& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM2B_DIGEST(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_OPERAND(
|
|
std::string* buffer,
|
|
TPM2B_OPERAND* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_ALG_ID(
|
|
const TPM_ALG_ID& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_ALG_ID(
|
|
std::string* buffer,
|
|
TPM_ALG_ID* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_HASH(
|
|
const TPMI_ALG_HASH& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_HASH(
|
|
std::string* buffer,
|
|
TPMI_ALG_HASH* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_SIGHASH(
|
|
const TPMS_SCHEME_SIGHASH& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_SIGHASH(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_SIGHASH* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_HMAC(
|
|
const TPMS_SCHEME_HMAC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_HMAC(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_HMAC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_RSASSA(
|
|
const TPMS_SCHEME_RSASSA& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_RSASSA(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_RSASSA* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_RSAPSS(
|
|
const TPMS_SCHEME_RSAPSS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_RSAPSS(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_RSAPSS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_ECDSA(
|
|
const TPMS_SCHEME_ECDSA& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_ECDSA(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_ECDSA* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_SM2(
|
|
const TPMS_SCHEME_SM2& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_SM2(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_SM2* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_ECSCHNORR(
|
|
const TPMS_SCHEME_ECSCHNORR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_ECSCHNORR(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_ECSCHNORR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_YES_NO(
|
|
const TPMI_YES_NO& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_BYTE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_YES_NO(
|
|
std::string* buffer,
|
|
TPMI_YES_NO* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_BYTE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_DH_OBJECT(
|
|
const TPMI_DH_OBJECT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_DH_OBJECT(
|
|
std::string* buffer,
|
|
TPMI_DH_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_DH_PERSISTENT(
|
|
const TPMI_DH_PERSISTENT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_DH_PERSISTENT(
|
|
std::string* buffer,
|
|
TPMI_DH_PERSISTENT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_DH_ENTITY(
|
|
const TPMI_DH_ENTITY& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_DH_ENTITY(
|
|
std::string* buffer,
|
|
TPMI_DH_ENTITY* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_DH_PCR(
|
|
const TPMI_DH_PCR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_DH_PCR(
|
|
std::string* buffer,
|
|
TPMI_DH_PCR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_SH_AUTH_SESSION(
|
|
const TPMI_SH_AUTH_SESSION& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_SH_AUTH_SESSION(
|
|
std::string* buffer,
|
|
TPMI_SH_AUTH_SESSION* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_SH_HMAC(
|
|
const TPMI_SH_HMAC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_SH_HMAC(
|
|
std::string* buffer,
|
|
TPMI_SH_HMAC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_SH_POLICY(
|
|
const TPMI_SH_POLICY& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_SH_POLICY(
|
|
std::string* buffer,
|
|
TPMI_SH_POLICY* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_DH_CONTEXT(
|
|
const TPMI_DH_CONTEXT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_DH_CONTEXT(
|
|
std::string* buffer,
|
|
TPMI_DH_CONTEXT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_HIERARCHY(
|
|
const TPMI_RH_HIERARCHY& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_HIERARCHY(
|
|
std::string* buffer,
|
|
TPMI_RH_HIERARCHY* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_ENABLES(
|
|
const TPMI_RH_ENABLES& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_ENABLES(
|
|
std::string* buffer,
|
|
TPMI_RH_ENABLES* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_HIERARCHY_AUTH(
|
|
const TPMI_RH_HIERARCHY_AUTH& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_HIERARCHY_AUTH(
|
|
std::string* buffer,
|
|
TPMI_RH_HIERARCHY_AUTH* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_PLATFORM(
|
|
const TPMI_RH_PLATFORM& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_PLATFORM(
|
|
std::string* buffer,
|
|
TPMI_RH_PLATFORM* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_OWNER(
|
|
const TPMI_RH_OWNER& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_OWNER(
|
|
std::string* buffer,
|
|
TPMI_RH_OWNER* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_ENDORSEMENT(
|
|
const TPMI_RH_ENDORSEMENT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_ENDORSEMENT(
|
|
std::string* buffer,
|
|
TPMI_RH_ENDORSEMENT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_PROVISION(
|
|
const TPMI_RH_PROVISION& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_PROVISION(
|
|
std::string* buffer,
|
|
TPMI_RH_PROVISION* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_CLEAR(
|
|
const TPMI_RH_CLEAR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_CLEAR(
|
|
std::string* buffer,
|
|
TPMI_RH_CLEAR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_NV_AUTH(
|
|
const TPMI_RH_NV_AUTH& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_NV_AUTH(
|
|
std::string* buffer,
|
|
TPMI_RH_NV_AUTH* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_LOCKOUT(
|
|
const TPMI_RH_LOCKOUT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_LOCKOUT(
|
|
std::string* buffer,
|
|
TPMI_RH_LOCKOUT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RH_NV_INDEX(
|
|
const TPMI_RH_NV_INDEX& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RH_NV_INDEX(
|
|
std::string* buffer,
|
|
TPMI_RH_NV_INDEX* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_ASYM(
|
|
const TPMI_ALG_ASYM& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_ASYM(
|
|
std::string* buffer,
|
|
TPMI_ALG_ASYM* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_SYM(
|
|
const TPMI_ALG_SYM& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_SYM(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_SYM_OBJECT(
|
|
const TPMI_ALG_SYM_OBJECT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_SYM_OBJECT(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_SYM_MODE(
|
|
const TPMI_ALG_SYM_MODE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_SYM_MODE(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM_MODE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_KDF(
|
|
const TPMI_ALG_KDF& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_KDF(
|
|
std::string* buffer,
|
|
TPMI_ALG_KDF* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_SIG_SCHEME(
|
|
const TPMI_ALG_SIG_SCHEME& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_SIG_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_SIG_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ECC_KEY_EXCHANGE(
|
|
const TPMI_ECC_KEY_EXCHANGE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ECC_KEY_EXCHANGE(
|
|
std::string* buffer,
|
|
TPMI_ECC_KEY_EXCHANGE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_ST(
|
|
const TPM_ST& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_ST(
|
|
std::string* buffer,
|
|
TPM_ST* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ST_COMMAND_TAG(
|
|
const TPMI_ST_COMMAND_TAG& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ST(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ST_COMMAND_TAG(
|
|
std::string* buffer,
|
|
TPMI_ST_COMMAND_TAG* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ST(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ST_ATTEST(
|
|
const TPMI_ST_ATTEST& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ST(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ST_ATTEST(
|
|
std::string* buffer,
|
|
TPMI_ST_ATTEST* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ST(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_AES_KEY_BITS(
|
|
const TPMI_AES_KEY_BITS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_KEY_BITS(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_AES_KEY_BITS(
|
|
std::string* buffer,
|
|
TPMI_AES_KEY_BITS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_SM4_KEY_BITS(
|
|
const TPMI_SM4_KEY_BITS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_KEY_BITS(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_SM4_KEY_BITS(
|
|
std::string* buffer,
|
|
TPMI_SM4_KEY_BITS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_KEYEDHASH_SCHEME(
|
|
const TPMI_ALG_KEYEDHASH_SCHEME& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_KEYEDHASH_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_KEYEDHASH_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_ASYM_SCHEME(
|
|
const TPMI_ALG_ASYM_SCHEME& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_ASYM_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_ASYM_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_RSA_SCHEME(
|
|
const TPMI_ALG_RSA_SCHEME& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_RSA_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_RSA_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_RSA_DECRYPT(
|
|
const TPMI_ALG_RSA_DECRYPT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_RSA_DECRYPT(
|
|
std::string* buffer,
|
|
TPMI_ALG_RSA_DECRYPT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_RSA_KEY_BITS(
|
|
const TPMI_RSA_KEY_BITS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_KEY_BITS(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_RSA_KEY_BITS(
|
|
std::string* buffer,
|
|
TPMI_RSA_KEY_BITS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_ECC_SCHEME(
|
|
const TPMI_ALG_ECC_SCHEME& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_ECC_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_ECC_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_ECC_CURVE(
|
|
const TPM_ECC_CURVE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_ECC_CURVE(
|
|
std::string* buffer,
|
|
TPM_ECC_CURVE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ECC_CURVE(
|
|
const TPMI_ECC_CURVE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ECC_CURVE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ECC_CURVE(
|
|
std::string* buffer,
|
|
TPMI_ECC_CURVE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ECC_CURVE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMI_ALG_PUBLIC(
|
|
const TPMI_ALG_PUBLIC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_ALG_ID(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMI_ALG_PUBLIC(
|
|
std::string* buffer,
|
|
TPMI_ALG_PUBLIC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_ALG_ID(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_ALGORITHM(
|
|
const TPMA_ALGORITHM& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_ALGORITHM(
|
|
std::string* buffer,
|
|
TPMA_ALGORITHM* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_OBJECT(
|
|
const TPMA_OBJECT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_OBJECT(
|
|
std::string* buffer,
|
|
TPMA_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_SESSION(
|
|
const TPMA_SESSION& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT8(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_SESSION(
|
|
std::string* buffer,
|
|
TPMA_SESSION* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT8(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_LOCALITY(
|
|
const TPMA_LOCALITY& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT8(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_LOCALITY(
|
|
std::string* buffer,
|
|
TPMA_LOCALITY* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT8(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_PERMANENT(
|
|
const TPMA_PERMANENT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_PERMANENT(
|
|
std::string* buffer,
|
|
TPMA_PERMANENT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_STARTUP_CLEAR(
|
|
const TPMA_STARTUP_CLEAR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_STARTUP_CLEAR(
|
|
std::string* buffer,
|
|
TPMA_STARTUP_CLEAR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_MEMORY(
|
|
const TPMA_MEMORY& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_MEMORY(
|
|
std::string* buffer,
|
|
TPMA_MEMORY* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_CC(
|
|
const TPM_CC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_CC(
|
|
std::string* buffer,
|
|
TPM_CC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_CC(
|
|
const TPMA_CC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_CC(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_CC(
|
|
std::string* buffer,
|
|
TPMA_CC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_CC(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_NV_INDEX(
|
|
const TPM_NV_INDEX& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_NV_INDEX(
|
|
std::string* buffer,
|
|
TPM_NV_INDEX* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMA_NV(
|
|
const TPMA_NV& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPMA_NV(
|
|
std::string* buffer,
|
|
TPMA_NV* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_SPEC(
|
|
const TPM_SPEC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_SPEC(
|
|
std::string* buffer,
|
|
TPM_SPEC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_GENERATED(
|
|
const TPM_GENERATED& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_GENERATED(
|
|
std::string* buffer,
|
|
TPM_GENERATED* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_RC(
|
|
const TPM_RC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_RC(
|
|
std::string* buffer,
|
|
TPM_RC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_CLOCK_ADJUST(
|
|
const TPM_CLOCK_ADJUST& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_INT8(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_CLOCK_ADJUST(
|
|
std::string* buffer,
|
|
TPM_CLOCK_ADJUST* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_INT8(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_EO(
|
|
const TPM_EO& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_EO(
|
|
std::string* buffer,
|
|
TPM_EO* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_SU(
|
|
const TPM_SU& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT16(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_SU(
|
|
std::string* buffer,
|
|
TPM_SU* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT16(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_SE(
|
|
const TPM_SE& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT8(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_SE(
|
|
std::string* buffer,
|
|
TPM_SE* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT8(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_CAP(
|
|
const TPM_CAP& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_CAP(
|
|
std::string* buffer,
|
|
TPM_CAP* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_PT(
|
|
const TPM_PT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_PT(
|
|
std::string* buffer,
|
|
TPM_PT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_PT_PCR(
|
|
const TPM_PT_PCR& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_PT_PCR(
|
|
std::string* buffer,
|
|
TPM_PT_PCR* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_PS(
|
|
const TPM_PS& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_PS(
|
|
std::string* buffer,
|
|
TPM_PS* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_HT(
|
|
const TPM_HT& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT8(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_HT(
|
|
std::string* buffer,
|
|
TPM_HT* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT8(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_RH(
|
|
const TPM_RH& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_UINT32(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_RH(
|
|
std::string* buffer,
|
|
TPM_RH* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_UINT32(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM_HC(
|
|
const TPM_HC& value,
|
|
std::string* buffer) {
|
|
VLOG(3) << __func__;
|
|
return Serialize_TPM_HANDLE(value, buffer);
|
|
}
|
|
|
|
TPM_RC Parse_TPM_HC(
|
|
std::string* buffer,
|
|
TPM_HC* value,
|
|
std::string* value_bytes) {
|
|
VLOG(3) << __func__;
|
|
return Parse_TPM_HANDLE(buffer, value, value_bytes);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ALGORITHM_DESCRIPTION(
|
|
const TPMS_ALGORITHM_DESCRIPTION& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ALG_ID(value.alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_ALGORITHM(value.attributes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ALGORITHM_DESCRIPTION(
|
|
std::string* buffer,
|
|
TPMS_ALGORITHM_DESCRIPTION* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ALG_ID(
|
|
buffer,
|
|
&value->alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_ALGORITHM(
|
|
buffer,
|
|
&value->attributes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_HA(
|
|
const TPMU_HA& value,
|
|
TPMI_ALG_HASH selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_SHA384) {
|
|
if (arraysize(value.sha384) < SHA384_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA384_DIGEST_SIZE; ++i) {
|
|
result = Serialize_BYTE(value.sha384[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA1) {
|
|
if (arraysize(value.sha1) < SHA1_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA1_DIGEST_SIZE; ++i) {
|
|
result = Serialize_BYTE(value.sha1[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM3_256) {
|
|
if (arraysize(value.sm3_256) < SM3_256_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SM3_256_DIGEST_SIZE; ++i) {
|
|
result = Serialize_BYTE(value.sm3_256[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA256) {
|
|
if (arraysize(value.sha256) < SHA256_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA256_DIGEST_SIZE; ++i) {
|
|
result = Serialize_BYTE(value.sha256[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA512) {
|
|
if (arraysize(value.sha512) < SHA512_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA512_DIGEST_SIZE; ++i) {
|
|
result = Serialize_BYTE(value.sha512[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_HA(
|
|
std::string* buffer,
|
|
TPMI_ALG_HASH selector,
|
|
TPMU_HA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_SHA384) {
|
|
if (arraysize(value->sha384) < SHA384_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA384_DIGEST_SIZE; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->sha384[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA1) {
|
|
if (arraysize(value->sha1) < SHA1_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA1_DIGEST_SIZE; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->sha1[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM3_256) {
|
|
if (arraysize(value->sm3_256) < SM3_256_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SM3_256_DIGEST_SIZE; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->sm3_256[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA256) {
|
|
if (arraysize(value->sha256) < SHA256_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA256_DIGEST_SIZE; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->sha256[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SHA512) {
|
|
if (arraysize(value->sha512) < SHA512_DIGEST_SIZE) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < SHA512_DIGEST_SIZE; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->sha512[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_HA(
|
|
const TPMT_HA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_HA(
|
|
value.digest,
|
|
value.hash_alg,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_HA(
|
|
std::string* buffer,
|
|
TPMT_HA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_HA(
|
|
buffer,
|
|
value->hash_alg,
|
|
&value->digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_DATA(
|
|
const TPM2B_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_DATA(
|
|
std::string* buffer,
|
|
TPM2B_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_DATA Make_TPM2B_DATA(
|
|
const std::string& bytes) {
|
|
TPM2B_DATA tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_DATA));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_DATA(
|
|
const TPM2B_DATA& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_EVENT(
|
|
const TPM2B_EVENT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_EVENT(
|
|
std::string* buffer,
|
|
TPM2B_EVENT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_EVENT Make_TPM2B_EVENT(
|
|
const std::string& bytes) {
|
|
TPM2B_EVENT tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_EVENT));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_EVENT(
|
|
const TPM2B_EVENT& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_MAX_BUFFER(
|
|
const TPM2B_MAX_BUFFER& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_MAX_BUFFER(
|
|
std::string* buffer,
|
|
TPM2B_MAX_BUFFER* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_MAX_BUFFER Make_TPM2B_MAX_BUFFER(
|
|
const std::string& bytes) {
|
|
TPM2B_MAX_BUFFER tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_MAX_BUFFER));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_MAX_BUFFER(
|
|
const TPM2B_MAX_BUFFER& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_MAX_NV_BUFFER(
|
|
const TPM2B_MAX_NV_BUFFER& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_MAX_NV_BUFFER(
|
|
std::string* buffer,
|
|
TPM2B_MAX_NV_BUFFER* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_MAX_NV_BUFFER Make_TPM2B_MAX_NV_BUFFER(
|
|
const std::string& bytes) {
|
|
TPM2B_MAX_NV_BUFFER tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_MAX_NV_BUFFER));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_MAX_NV_BUFFER(
|
|
const TPM2B_MAX_NV_BUFFER& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_TIMEOUT(
|
|
const TPM2B_TIMEOUT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_TIMEOUT(
|
|
std::string* buffer,
|
|
TPM2B_TIMEOUT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_TIMEOUT Make_TPM2B_TIMEOUT(
|
|
const std::string& bytes) {
|
|
TPM2B_TIMEOUT tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_TIMEOUT));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_TIMEOUT(
|
|
const TPM2B_TIMEOUT& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_IV(
|
|
const TPM2B_IV& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_IV(
|
|
std::string* buffer,
|
|
TPM2B_IV* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_IV Make_TPM2B_IV(
|
|
const std::string& bytes) {
|
|
TPM2B_IV tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_IV));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_IV(
|
|
const TPM2B_IV& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_NAME(
|
|
const TPM2B_NAME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.name) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.name[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_NAME(
|
|
std::string* buffer,
|
|
TPM2B_NAME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->name) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->name[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_NAME Make_TPM2B_NAME(
|
|
const std::string& bytes) {
|
|
TPM2B_NAME tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.name));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_NAME));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.name, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_NAME(
|
|
const TPM2B_NAME& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.name);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_PCR_SELECT(
|
|
const TPMS_PCR_SELECT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT8(value.sizeof_select, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.pcr_select) < value.sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.sizeof_select; ++i) {
|
|
result = Serialize_BYTE(value.pcr_select[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_PCR_SELECT(
|
|
std::string* buffer,
|
|
TPMS_PCR_SELECT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT8(
|
|
buffer,
|
|
&value->sizeof_select,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->pcr_select) < value->sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->sizeof_select; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->pcr_select[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_PCR_SELECTION(
|
|
const TPMS_PCR_SELECTION& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT8(value.sizeof_select, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.pcr_select) < value.sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.sizeof_select; ++i) {
|
|
result = Serialize_BYTE(value.pcr_select[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_PCR_SELECTION(
|
|
std::string* buffer,
|
|
TPMS_PCR_SELECTION* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT8(
|
|
buffer,
|
|
&value->sizeof_select,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->pcr_select) < value->sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->sizeof_select; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->pcr_select[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_TK_CREATION(
|
|
const TPMT_TK_CREATION& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ST(value.tag, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_TK_CREATION(
|
|
std::string* buffer,
|
|
TPMT_TK_CREATION* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ST(
|
|
buffer,
|
|
&value->tag,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_RH_HIERARCHY(
|
|
buffer,
|
|
&value->hierarchy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_TK_VERIFIED(
|
|
const TPMT_TK_VERIFIED& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ST(value.tag, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_TK_VERIFIED(
|
|
std::string* buffer,
|
|
TPMT_TK_VERIFIED* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ST(
|
|
buffer,
|
|
&value->tag,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_RH_HIERARCHY(
|
|
buffer,
|
|
&value->hierarchy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_TK_AUTH(
|
|
const TPMT_TK_AUTH& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_TK_AUTH(
|
|
std::string* buffer,
|
|
TPMT_TK_AUTH* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_RH_HIERARCHY(
|
|
buffer,
|
|
&value->hierarchy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_TK_HASHCHECK(
|
|
const TPMT_TK_HASHCHECK& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ST(value.tag, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_TK_HASHCHECK(
|
|
std::string* buffer,
|
|
TPMT_TK_HASHCHECK* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ST(
|
|
buffer,
|
|
&value->tag,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_RH_HIERARCHY(
|
|
buffer,
|
|
&value->hierarchy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ALG_PROPERTY(
|
|
const TPMS_ALG_PROPERTY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ALG_ID(value.alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_ALGORITHM(value.alg_properties, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ALG_PROPERTY(
|
|
std::string* buffer,
|
|
TPMS_ALG_PROPERTY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ALG_ID(
|
|
buffer,
|
|
&value->alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_ALGORITHM(
|
|
buffer,
|
|
&value->alg_properties,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_TAGGED_PROPERTY(
|
|
const TPMS_TAGGED_PROPERTY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_PT(value.property, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT32(value.value, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_TAGGED_PROPERTY(
|
|
std::string* buffer,
|
|
TPMS_TAGGED_PROPERTY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_PT(
|
|
buffer,
|
|
&value->property,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->value,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_TAGGED_PCR_SELECT(
|
|
const TPMS_TAGGED_PCR_SELECT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_PT(value.tag, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT8(value.sizeof_select, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.pcr_select) < value.sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.sizeof_select; ++i) {
|
|
result = Serialize_BYTE(value.pcr_select[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_TAGGED_PCR_SELECT(
|
|
std::string* buffer,
|
|
TPMS_TAGGED_PCR_SELECT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_PT(
|
|
buffer,
|
|
&value->tag,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT8(
|
|
buffer,
|
|
&value->sizeof_select,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->pcr_select) < value->sizeof_select) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->sizeof_select; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->pcr_select[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_CC(
|
|
const TPML_CC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.command_codes) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPM_CC(value.command_codes[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_CC(
|
|
std::string* buffer,
|
|
TPML_CC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->command_codes) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPM_CC(
|
|
buffer,
|
|
&value->command_codes[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_CCA(
|
|
const TPML_CCA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.command_attributes) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMA_CC(value.command_attributes[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_CCA(
|
|
std::string* buffer,
|
|
TPML_CCA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->command_attributes) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMA_CC(
|
|
buffer,
|
|
&value->command_attributes[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_ALG(
|
|
const TPML_ALG& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.algorithms) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPM_ALG_ID(value.algorithms[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_ALG(
|
|
std::string* buffer,
|
|
TPML_ALG* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->algorithms) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPM_ALG_ID(
|
|
buffer,
|
|
&value->algorithms[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_HANDLE(
|
|
const TPML_HANDLE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.handle) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPM_HANDLE(value.handle[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_HANDLE(
|
|
std::string* buffer,
|
|
TPML_HANDLE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->handle) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPM_HANDLE(
|
|
buffer,
|
|
&value->handle[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_DIGEST(
|
|
const TPML_DIGEST& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.digests) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPM2B_DIGEST(value.digests[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_DIGEST(
|
|
std::string* buffer,
|
|
TPML_DIGEST* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->digests) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->digests[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_DIGEST_VALUES(
|
|
const TPML_DIGEST_VALUES& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.digests) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMT_HA(value.digests[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_DIGEST_VALUES(
|
|
std::string* buffer,
|
|
TPML_DIGEST_VALUES* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->digests) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMT_HA(
|
|
buffer,
|
|
&value->digests[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_DIGEST_VALUES(
|
|
const TPM2B_DIGEST_VALUES& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_DIGEST_VALUES(
|
|
std::string* buffer,
|
|
TPM2B_DIGEST_VALUES* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_DIGEST_VALUES Make_TPM2B_DIGEST_VALUES(
|
|
const std::string& bytes) {
|
|
TPM2B_DIGEST_VALUES tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_DIGEST_VALUES));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_DIGEST_VALUES(
|
|
const TPM2B_DIGEST_VALUES& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_PCR_SELECTION(
|
|
const TPML_PCR_SELECTION& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.pcr_selections) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMS_PCR_SELECTION(value.pcr_selections[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_PCR_SELECTION(
|
|
std::string* buffer,
|
|
TPML_PCR_SELECTION* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->pcr_selections) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMS_PCR_SELECTION(
|
|
buffer,
|
|
&value->pcr_selections[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_ALG_PROPERTY(
|
|
const TPML_ALG_PROPERTY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.alg_properties) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMS_ALG_PROPERTY(value.alg_properties[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_ALG_PROPERTY(
|
|
std::string* buffer,
|
|
TPML_ALG_PROPERTY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->alg_properties) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMS_ALG_PROPERTY(
|
|
buffer,
|
|
&value->alg_properties[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_TAGGED_TPM_PROPERTY(
|
|
const TPML_TAGGED_TPM_PROPERTY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.tpm_property) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMS_TAGGED_PROPERTY(value.tpm_property[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_TAGGED_TPM_PROPERTY(
|
|
std::string* buffer,
|
|
TPML_TAGGED_TPM_PROPERTY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->tpm_property) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMS_TAGGED_PROPERTY(
|
|
buffer,
|
|
&value->tpm_property[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_TAGGED_PCR_PROPERTY(
|
|
const TPML_TAGGED_PCR_PROPERTY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.pcr_property) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPMS_TAGGED_PCR_SELECT(value.pcr_property[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_TAGGED_PCR_PROPERTY(
|
|
std::string* buffer,
|
|
TPML_TAGGED_PCR_PROPERTY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->pcr_property) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPMS_TAGGED_PCR_SELECT(
|
|
buffer,
|
|
&value->pcr_property[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPML_ECC_CURVE(
|
|
const TPML_ECC_CURVE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT32(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.ecc_curves) < value.count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.count; ++i) {
|
|
result = Serialize_TPM_ECC_CURVE(value.ecc_curves[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPML_ECC_CURVE(
|
|
std::string* buffer,
|
|
TPML_ECC_CURVE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->ecc_curves) < value->count) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->count; ++i) {
|
|
result = Parse_TPM_ECC_CURVE(
|
|
buffer,
|
|
&value->ecc_curves[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_CAPABILITIES(
|
|
const TPMU_CAPABILITIES& value,
|
|
TPM_CAP selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_CAP_PCRS) {
|
|
result = Serialize_TPML_PCR_SELECTION(value.assigned_pcr, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_TPM_PROPERTIES) {
|
|
result = Serialize_TPML_TAGGED_TPM_PROPERTY(value.tpm_properties, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_PP_COMMANDS) {
|
|
result = Serialize_TPML_CC(value.pp_commands, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_AUDIT_COMMANDS) {
|
|
result = Serialize_TPML_CC(value.audit_commands, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_COMMANDS) {
|
|
result = Serialize_TPML_CCA(value.command, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_ECC_CURVES) {
|
|
result = Serialize_TPML_ECC_CURVE(value.ecc_curves, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_PCR_PROPERTIES) {
|
|
result = Serialize_TPML_TAGGED_PCR_PROPERTY(value.pcr_properties, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_HANDLES) {
|
|
result = Serialize_TPML_HANDLE(value.handles, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_ALGS) {
|
|
result = Serialize_TPML_ALG_PROPERTY(value.algorithms, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_CAPABILITIES(
|
|
std::string* buffer,
|
|
TPM_CAP selector,
|
|
TPMU_CAPABILITIES* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_CAP_PCRS) {
|
|
result = Parse_TPML_PCR_SELECTION(
|
|
buffer,
|
|
&value->assigned_pcr,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_TPM_PROPERTIES) {
|
|
result = Parse_TPML_TAGGED_TPM_PROPERTY(
|
|
buffer,
|
|
&value->tpm_properties,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_PP_COMMANDS) {
|
|
result = Parse_TPML_CC(
|
|
buffer,
|
|
&value->pp_commands,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_AUDIT_COMMANDS) {
|
|
result = Parse_TPML_CC(
|
|
buffer,
|
|
&value->audit_commands,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_COMMANDS) {
|
|
result = Parse_TPML_CCA(
|
|
buffer,
|
|
&value->command,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_ECC_CURVES) {
|
|
result = Parse_TPML_ECC_CURVE(
|
|
buffer,
|
|
&value->ecc_curves,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_PCR_PROPERTIES) {
|
|
result = Parse_TPML_TAGGED_PCR_PROPERTY(
|
|
buffer,
|
|
&value->pcr_properties,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_HANDLES) {
|
|
result = Parse_TPML_HANDLE(
|
|
buffer,
|
|
&value->handles,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_CAP_ALGS) {
|
|
result = Parse_TPML_ALG_PROPERTY(
|
|
buffer,
|
|
&value->algorithms,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CAPABILITY_DATA(
|
|
const TPMS_CAPABILITY_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_CAP(value.capability, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_CAPABILITIES(
|
|
value.data,
|
|
value.capability,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CAPABILITY_DATA(
|
|
std::string* buffer,
|
|
TPMS_CAPABILITY_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_CAP(
|
|
buffer,
|
|
&value->capability,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_CAPABILITIES(
|
|
buffer,
|
|
value->capability,
|
|
&value->data,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CLOCK_INFO(
|
|
const TPMS_CLOCK_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT64(value.clock, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT32(value.reset_count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT32(value.restart_count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_YES_NO(value.safe, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CLOCK_INFO(
|
|
std::string* buffer,
|
|
TPMS_CLOCK_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->clock,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->reset_count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->restart_count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_YES_NO(
|
|
buffer,
|
|
&value->safe,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_TIME_INFO(
|
|
const TPMS_TIME_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT64(value.time, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMS_CLOCK_INFO(value.clock_info, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_TIME_INFO(
|
|
std::string* buffer,
|
|
TPMS_TIME_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->time,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_CLOCK_INFO(
|
|
buffer,
|
|
&value->clock_info,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_TIME_ATTEST_INFO(
|
|
const TPMS_TIME_ATTEST_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMS_TIME_INFO(value.time, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT64(value.firmware_version, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_TIME_ATTEST_INFO(
|
|
std::string* buffer,
|
|
TPMS_TIME_ATTEST_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMS_TIME_INFO(
|
|
buffer,
|
|
&value->time,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->firmware_version,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CERTIFY_INFO(
|
|
const TPMS_CERTIFY_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_NAME(value.name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_NAME(value.qualified_name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CERTIFY_INFO(
|
|
std::string* buffer,
|
|
TPMS_CERTIFY_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->qualified_name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_QUOTE_INFO(
|
|
const TPMS_QUOTE_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPML_PCR_SELECTION(value.pcr_select, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.pcr_digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_QUOTE_INFO(
|
|
std::string* buffer,
|
|
TPMS_QUOTE_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPML_PCR_SELECTION(
|
|
buffer,
|
|
&value->pcr_select,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->pcr_digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_COMMAND_AUDIT_INFO(
|
|
const TPMS_COMMAND_AUDIT_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT64(value.audit_counter, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM_ALG_ID(value.digest_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.audit_digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.command_digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_COMMAND_AUDIT_INFO(
|
|
std::string* buffer,
|
|
TPMS_COMMAND_AUDIT_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->audit_counter,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM_ALG_ID(
|
|
buffer,
|
|
&value->digest_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->audit_digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->command_digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SESSION_AUDIT_INFO(
|
|
const TPMS_SESSION_AUDIT_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_YES_NO(value.exclusive_session, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.session_digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SESSION_AUDIT_INFO(
|
|
std::string* buffer,
|
|
TPMS_SESSION_AUDIT_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_YES_NO(
|
|
buffer,
|
|
&value->exclusive_session,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->session_digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CREATION_INFO(
|
|
const TPMS_CREATION_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_NAME(value.object_name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.creation_hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CREATION_INFO(
|
|
std::string* buffer,
|
|
TPMS_CREATION_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->object_name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->creation_hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_NV_CERTIFY_INFO(
|
|
const TPMS_NV_CERTIFY_INFO& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_NAME(value.index_name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT16(value.offset, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_MAX_NV_BUFFER(value.nv_contents, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_NV_CERTIFY_INFO(
|
|
std::string* buffer,
|
|
TPMS_NV_CERTIFY_INFO* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->index_name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->offset,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_MAX_NV_BUFFER(
|
|
buffer,
|
|
&value->nv_contents,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_ATTEST(
|
|
const TPMU_ATTEST& value,
|
|
TPMI_ST_ATTEST selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ST_ATTEST_SESSION_AUDIT) {
|
|
result = Serialize_TPMS_SESSION_AUDIT_INFO(value.session_audit, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_QUOTE) {
|
|
result = Serialize_TPMS_QUOTE_INFO(value.quote, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_COMMAND_AUDIT) {
|
|
result = Serialize_TPMS_COMMAND_AUDIT_INFO(value.command_audit, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_CERTIFY) {
|
|
result = Serialize_TPMS_CERTIFY_INFO(value.certify, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_NV) {
|
|
result = Serialize_TPMS_NV_CERTIFY_INFO(value.nv, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_TIME) {
|
|
result = Serialize_TPMS_TIME_ATTEST_INFO(value.time, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_CREATION) {
|
|
result = Serialize_TPMS_CREATION_INFO(value.creation, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_ATTEST(
|
|
std::string* buffer,
|
|
TPMI_ST_ATTEST selector,
|
|
TPMU_ATTEST* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ST_ATTEST_SESSION_AUDIT) {
|
|
result = Parse_TPMS_SESSION_AUDIT_INFO(
|
|
buffer,
|
|
&value->session_audit,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_QUOTE) {
|
|
result = Parse_TPMS_QUOTE_INFO(
|
|
buffer,
|
|
&value->quote,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_COMMAND_AUDIT) {
|
|
result = Parse_TPMS_COMMAND_AUDIT_INFO(
|
|
buffer,
|
|
&value->command_audit,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_CERTIFY) {
|
|
result = Parse_TPMS_CERTIFY_INFO(
|
|
buffer,
|
|
&value->certify,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_NV) {
|
|
result = Parse_TPMS_NV_CERTIFY_INFO(
|
|
buffer,
|
|
&value->nv,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_TIME) {
|
|
result = Parse_TPMS_TIME_ATTEST_INFO(
|
|
buffer,
|
|
&value->time,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ST_ATTEST_CREATION) {
|
|
result = Parse_TPMS_CREATION_INFO(
|
|
buffer,
|
|
&value->creation,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ATTEST(
|
|
const TPMS_ATTEST& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_GENERATED(value.magic, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_ST_ATTEST(value.type, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_NAME(value.qualified_signer, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DATA(value.extra_data, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMS_CLOCK_INFO(value.clock_info, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT64(value.firmware_version, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_ATTEST(
|
|
value.attested,
|
|
value.type,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ATTEST(
|
|
std::string* buffer,
|
|
TPMS_ATTEST* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_GENERATED(
|
|
buffer,
|
|
&value->magic,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_ST_ATTEST(
|
|
buffer,
|
|
&value->type,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->qualified_signer,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DATA(
|
|
buffer,
|
|
&value->extra_data,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_CLOCK_INFO(
|
|
buffer,
|
|
&value->clock_info,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->firmware_version,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_ATTEST(
|
|
buffer,
|
|
value->type,
|
|
&value->attested,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_ATTEST(
|
|
const TPM2B_ATTEST& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.attestation_data) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.attestation_data[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_ATTEST(
|
|
std::string* buffer,
|
|
TPM2B_ATTEST* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->attestation_data) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->attestation_data[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_ATTEST Make_TPM2B_ATTEST(
|
|
const std::string& bytes) {
|
|
TPM2B_ATTEST tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.attestation_data));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_ATTEST));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.attestation_data, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_ATTEST(
|
|
const TPM2B_ATTEST& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.attestation_data);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_AUTH_COMMAND(
|
|
const TPMS_AUTH_COMMAND& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_SH_AUTH_SESSION(value.session_handle, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_NONCE(value.nonce, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_SESSION(value.session_attributes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_AUTH(value.hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_AUTH_COMMAND(
|
|
std::string* buffer,
|
|
TPMS_AUTH_COMMAND* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_SH_AUTH_SESSION(
|
|
buffer,
|
|
&value->session_handle,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_NONCE(
|
|
buffer,
|
|
&value->nonce,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_SESSION(
|
|
buffer,
|
|
&value->session_attributes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_AUTH(
|
|
buffer,
|
|
&value->hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_AUTH_RESPONSE(
|
|
const TPMS_AUTH_RESPONSE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_NONCE(value.nonce, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_SESSION(value.session_attributes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_AUTH(value.hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_AUTH_RESPONSE(
|
|
std::string* buffer,
|
|
TPMS_AUTH_RESPONSE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_NONCE(
|
|
buffer,
|
|
&value->nonce,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_SESSION(
|
|
buffer,
|
|
&value->session_attributes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_AUTH(
|
|
buffer,
|
|
&value->hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SYM_KEY_BITS(
|
|
const TPMU_SYM_KEY_BITS& value,
|
|
TPMI_ALG_SYM selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM4) {
|
|
result = Serialize_TPMI_SM4_KEY_BITS(value.sm4, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_AES) {
|
|
result = Serialize_TPMI_AES_KEY_BITS(value.aes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
result = Serialize_TPMI_ALG_HASH(value.xor_, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SYM_KEY_BITS(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM selector,
|
|
TPMU_SYM_KEY_BITS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM4) {
|
|
result = Parse_TPMI_SM4_KEY_BITS(
|
|
buffer,
|
|
&value->sm4,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_AES) {
|
|
result = Parse_TPMI_AES_KEY_BITS(
|
|
buffer,
|
|
&value->aes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->xor_,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SYM_MODE(
|
|
const TPMU_SYM_MODE& value,
|
|
TPMI_ALG_SYM selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM4) {
|
|
result = Serialize_TPMI_ALG_SYM_MODE(value.sm4, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_AES) {
|
|
result = Serialize_TPMI_ALG_SYM_MODE(value.aes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SYM_MODE(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM selector,
|
|
TPMU_SYM_MODE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM4) {
|
|
result = Parse_TPMI_ALG_SYM_MODE(
|
|
buffer,
|
|
&value->sm4,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_AES) {
|
|
result = Parse_TPMI_ALG_SYM_MODE(
|
|
buffer,
|
|
&value->aes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SYM_DETAILS(
|
|
const TPMU_SYM_DETAILS& value,
|
|
TPMI_ALG_SYM selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SYM_DETAILS(
|
|
std::string* buffer,
|
|
TPMI_ALG_SYM selector,
|
|
TPMU_SYM_DETAILS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_SYM_DEF(
|
|
const TPMT_SYM_DEF& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_SYM(value.algorithm, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_KEY_BITS(
|
|
value.key_bits,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_MODE(
|
|
value.mode,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_DETAILS(
|
|
value.details,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_SYM_DEF(
|
|
std::string* buffer,
|
|
TPMT_SYM_DEF* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_SYM(
|
|
buffer,
|
|
&value->algorithm,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_KEY_BITS(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->key_bits,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_MODE(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->mode,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_DETAILS(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_SYM_DEF_OBJECT(
|
|
const TPMT_SYM_DEF_OBJECT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_SYM_OBJECT(value.algorithm, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_KEY_BITS(
|
|
value.key_bits,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_MODE(
|
|
value.mode,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SYM_DETAILS(
|
|
value.details,
|
|
value.algorithm,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_SYM_DEF_OBJECT(
|
|
std::string* buffer,
|
|
TPMT_SYM_DEF_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_SYM_OBJECT(
|
|
buffer,
|
|
&value->algorithm,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_KEY_BITS(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->key_bits,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_MODE(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->mode,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SYM_DETAILS(
|
|
buffer,
|
|
value->algorithm,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_SYM_KEY(
|
|
const TPM2B_SYM_KEY& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_SYM_KEY(
|
|
std::string* buffer,
|
|
TPM2B_SYM_KEY* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_SYM_KEY Make_TPM2B_SYM_KEY(
|
|
const std::string& bytes) {
|
|
TPM2B_SYM_KEY tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_SYM_KEY));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_SYM_KEY(
|
|
const TPM2B_SYM_KEY& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SYMCIPHER_PARMS(
|
|
const TPMS_SYMCIPHER_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMT_SYM_DEF_OBJECT(value.sym, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SYMCIPHER_PARMS(
|
|
std::string* buffer,
|
|
TPMS_SYMCIPHER_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMT_SYM_DEF_OBJECT(
|
|
buffer,
|
|
&value->sym,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_SENSITIVE_DATA(
|
|
const TPM2B_SENSITIVE_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_SENSITIVE_DATA(
|
|
std::string* buffer,
|
|
TPM2B_SENSITIVE_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_SENSITIVE_DATA Make_TPM2B_SENSITIVE_DATA(
|
|
const std::string& bytes) {
|
|
TPM2B_SENSITIVE_DATA tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_SENSITIVE_DATA));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_SENSITIVE_DATA(
|
|
const TPM2B_SENSITIVE_DATA& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SENSITIVE_CREATE(
|
|
const TPMS_SENSITIVE_CREATE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_AUTH(value.user_auth, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_SENSITIVE_DATA(value.data, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SENSITIVE_CREATE(
|
|
std::string* buffer,
|
|
TPMS_SENSITIVE_CREATE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_AUTH(
|
|
buffer,
|
|
&value->user_auth,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_SENSITIVE_DATA(
|
|
buffer,
|
|
&value->data,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_SENSITIVE_CREATE(
|
|
const TPM2B_SENSITIVE_CREATE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMS_SENSITIVE_CREATE(value.sensitive, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_SENSITIVE_CREATE(
|
|
std::string* buffer,
|
|
TPM2B_SENSITIVE_CREATE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_SENSITIVE_CREATE(
|
|
buffer,
|
|
&value->sensitive,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_SENSITIVE_CREATE Make_TPM2B_SENSITIVE_CREATE(
|
|
const TPMS_SENSITIVE_CREATE& inner) {
|
|
TPM2B_SENSITIVE_CREATE tpm2b;
|
|
tpm2b.size = sizeof(TPMS_SENSITIVE_CREATE);
|
|
tpm2b.sensitive = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_XOR(
|
|
const TPMS_SCHEME_XOR& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_ALG_KDF(value.kdf, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_XOR(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_XOR* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_ALG_KDF(
|
|
buffer,
|
|
&value->kdf,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SCHEME_KEYEDHASH(
|
|
const TPMU_SCHEME_KEYEDHASH& value,
|
|
TPMI_ALG_KEYEDHASH_SCHEME selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Serialize_TPMS_SCHEME_HMAC(value.hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
result = Serialize_TPMS_SCHEME_XOR(value.xor_, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SCHEME_KEYEDHASH(
|
|
std::string* buffer,
|
|
TPMI_ALG_KEYEDHASH_SCHEME selector,
|
|
TPMU_SCHEME_KEYEDHASH* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Parse_TPMS_SCHEME_HMAC(
|
|
buffer,
|
|
&value->hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_XOR) {
|
|
result = Parse_TPMS_SCHEME_XOR(
|
|
buffer,
|
|
&value->xor_,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_KEYEDHASH_SCHEME(
|
|
const TPMT_KEYEDHASH_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_KEYEDHASH_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SCHEME_KEYEDHASH(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_KEYEDHASH_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_KEYEDHASH_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_KEYEDHASH_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SCHEME_KEYEDHASH(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_ECDAA(
|
|
const TPMS_SCHEME_ECDAA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT16(value.count, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_ECDAA(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_ECDAA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->count,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SIG_SCHEME(
|
|
const TPMU_SIG_SCHEME& value,
|
|
TPMI_ALG_SIG_SCHEME selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Serialize_TPMS_SCHEME_HMAC(value.hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Serialize_TPMS_SCHEME_ECSCHNORR(value.ec_schnorr, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Serialize_TPMS_SCHEME_RSAPSS(value.rsapss, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Serialize_TPMS_SCHEME_ECDAA(value.ecdaa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Serialize_TPMS_SCHEME_RSASSA(value.rsassa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Serialize_TPMS_SCHEME_SM2(value.sm2, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Serialize_TPMS_SCHEME_ECDSA(value.ecdsa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SIG_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_SIG_SCHEME selector,
|
|
TPMU_SIG_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Parse_TPMS_SCHEME_HMAC(
|
|
buffer,
|
|
&value->hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Parse_TPMS_SCHEME_ECSCHNORR(
|
|
buffer,
|
|
&value->ec_schnorr,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Parse_TPMS_SCHEME_RSAPSS(
|
|
buffer,
|
|
&value->rsapss,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Parse_TPMS_SCHEME_ECDAA(
|
|
buffer,
|
|
&value->ecdaa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Parse_TPMS_SCHEME_RSASSA(
|
|
buffer,
|
|
&value->rsassa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Parse_TPMS_SCHEME_SM2(
|
|
buffer,
|
|
&value->sm2,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Parse_TPMS_SCHEME_ECDSA(
|
|
buffer,
|
|
&value->ecdsa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_SIG_SCHEME(
|
|
const TPMT_SIG_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_SIG_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SIG_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_SIG_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_SIG_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_SIG_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SIG_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_OAEP(
|
|
const TPMS_SCHEME_OAEP& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_OAEP(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_OAEP* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_ECDH(
|
|
const TPMS_SCHEME_ECDH& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_ECDH(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_ECDH* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_MGF1(
|
|
const TPMS_SCHEME_MGF1& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_MGF1(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_MGF1* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_56a(
|
|
const TPMS_SCHEME_KDF1_SP800_56a& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_56a(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_KDF1_SP800_56a* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_KDF2(
|
|
const TPMS_SCHEME_KDF2& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_KDF2(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_KDF2* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_108(
|
|
const TPMS_SCHEME_KDF1_SP800_108& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_108(
|
|
std::string* buffer,
|
|
TPMS_SCHEME_KDF1_SP800_108* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_KDF_SCHEME(
|
|
const TPMU_KDF_SCHEME& value,
|
|
TPMI_ALG_KDF selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KDF1_SP800_56a) {
|
|
result = Serialize_TPMS_SCHEME_KDF1_SP800_56a(value.kdf1_sp800_56a, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_MGF1) {
|
|
result = Serialize_TPMS_SCHEME_MGF1(value.mgf1, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_KDF1_SP800_108) {
|
|
result = Serialize_TPMS_SCHEME_KDF1_SP800_108(value.kdf1_sp800_108, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_KDF2) {
|
|
result = Serialize_TPMS_SCHEME_KDF2(value.kdf2, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_KDF_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_KDF selector,
|
|
TPMU_KDF_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KDF1_SP800_56a) {
|
|
result = Parse_TPMS_SCHEME_KDF1_SP800_56a(
|
|
buffer,
|
|
&value->kdf1_sp800_56a,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_MGF1) {
|
|
result = Parse_TPMS_SCHEME_MGF1(
|
|
buffer,
|
|
&value->mgf1,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_KDF1_SP800_108) {
|
|
result = Parse_TPMS_SCHEME_KDF1_SP800_108(
|
|
buffer,
|
|
&value->kdf1_sp800_108,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_KDF2) {
|
|
result = Parse_TPMS_SCHEME_KDF2(
|
|
buffer,
|
|
&value->kdf2,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_KDF_SCHEME(
|
|
const TPMT_KDF_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_KDF(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_KDF_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_KDF_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_KDF_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_KDF(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_KDF_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_ASYM_SCHEME(
|
|
const TPMU_ASYM_SCHEME& value,
|
|
TPMI_ALG_ASYM_SCHEME selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_RSAES) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Serialize_TPMS_SCHEME_ECSCHNORR(value.ec_schnorr, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDH) {
|
|
result = Serialize_TPMS_SCHEME_ECDH(value.ecdh, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_OAEP) {
|
|
result = Serialize_TPMS_SCHEME_OAEP(value.oaep, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Serialize_TPMS_SCHEME_RSAPSS(value.rsapss, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Serialize_TPMS_SCHEME_ECDAA(value.ecdaa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Serialize_TPMS_SCHEME_RSASSA(value.rsassa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Serialize_TPMS_SCHEME_SM2(value.sm2, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Serialize_TPMS_SCHEME_ECDSA(value.ecdsa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_ASYM_SCHEME(
|
|
std::string* buffer,
|
|
TPMI_ALG_ASYM_SCHEME selector,
|
|
TPMU_ASYM_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_RSAES) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Parse_TPMS_SCHEME_ECSCHNORR(
|
|
buffer,
|
|
&value->ec_schnorr,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDH) {
|
|
result = Parse_TPMS_SCHEME_ECDH(
|
|
buffer,
|
|
&value->ecdh,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_OAEP) {
|
|
result = Parse_TPMS_SCHEME_OAEP(
|
|
buffer,
|
|
&value->oaep,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Parse_TPMS_SCHEME_RSAPSS(
|
|
buffer,
|
|
&value->rsapss,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Parse_TPMS_SCHEME_ECDAA(
|
|
buffer,
|
|
&value->ecdaa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Parse_TPMS_SCHEME_RSASSA(
|
|
buffer,
|
|
&value->rsassa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Parse_TPMS_SCHEME_SM2(
|
|
buffer,
|
|
&value->sm2,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Parse_TPMS_SCHEME_ECDSA(
|
|
buffer,
|
|
&value->ecdsa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_ASYM_SCHEME(
|
|
const TPMT_ASYM_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_ASYM_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_ASYM_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_ASYM_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_ASYM_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_ASYM_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_ASYM_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_RSA_SCHEME(
|
|
const TPMT_RSA_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_RSA_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_ASYM_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_RSA_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_RSA_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_RSA_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_ASYM_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_RSA_DECRYPT(
|
|
const TPMT_RSA_DECRYPT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_RSA_DECRYPT(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_ASYM_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_RSA_DECRYPT(
|
|
std::string* buffer,
|
|
TPMT_RSA_DECRYPT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_RSA_DECRYPT(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_ASYM_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_PUBLIC_KEY_RSA(
|
|
const TPM2B_PUBLIC_KEY_RSA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
std::string* buffer,
|
|
TPM2B_PUBLIC_KEY_RSA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_PUBLIC_KEY_RSA Make_TPM2B_PUBLIC_KEY_RSA(
|
|
const std::string& bytes) {
|
|
TPM2B_PUBLIC_KEY_RSA tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_PUBLIC_KEY_RSA));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_PUBLIC_KEY_RSA(
|
|
const TPM2B_PUBLIC_KEY_RSA& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_PRIVATE_KEY_RSA(
|
|
const TPM2B_PRIVATE_KEY_RSA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_PRIVATE_KEY_RSA(
|
|
std::string* buffer,
|
|
TPM2B_PRIVATE_KEY_RSA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_PRIVATE_KEY_RSA Make_TPM2B_PRIVATE_KEY_RSA(
|
|
const std::string& bytes) {
|
|
TPM2B_PRIVATE_KEY_RSA tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE_KEY_RSA));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_PRIVATE_KEY_RSA(
|
|
const TPM2B_PRIVATE_KEY_RSA& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_ECC_PARAMETER(
|
|
const TPM2B_ECC_PARAMETER& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_ECC_PARAMETER(
|
|
std::string* buffer,
|
|
TPM2B_ECC_PARAMETER* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_ECC_PARAMETER Make_TPM2B_ECC_PARAMETER(
|
|
const std::string& bytes) {
|
|
TPM2B_ECC_PARAMETER tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_ECC_PARAMETER));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_ECC_PARAMETER(
|
|
const TPM2B_ECC_PARAMETER& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ECC_POINT(
|
|
const TPMS_ECC_POINT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.x, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.y, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ECC_POINT(
|
|
std::string* buffer,
|
|
TPMS_ECC_POINT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->x,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->y,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_ECC_POINT(
|
|
const TPM2B_ECC_POINT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMS_ECC_POINT(value.point, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_ECC_POINT(
|
|
std::string* buffer,
|
|
TPM2B_ECC_POINT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_ECC_POINT(
|
|
buffer,
|
|
&value->point,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_ECC_POINT Make_TPM2B_ECC_POINT(
|
|
const TPMS_ECC_POINT& inner) {
|
|
TPM2B_ECC_POINT tpm2b;
|
|
tpm2b.size = sizeof(TPMS_ECC_POINT);
|
|
tpm2b.point = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_ECC_SCHEME(
|
|
const TPMT_ECC_SCHEME& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_ECC_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SIG_SCHEME(
|
|
value.details,
|
|
value.scheme,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_ECC_SCHEME(
|
|
std::string* buffer,
|
|
TPMT_ECC_SCHEME* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_ECC_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SIG_SCHEME(
|
|
buffer,
|
|
value->scheme,
|
|
&value->details,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ALGORITHM_DETAIL_ECC(
|
|
const TPMS_ALGORITHM_DETAIL_ECC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM_ECC_CURVE(value.curve_id, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT16(value.key_size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_KDF_SCHEME(value.kdf, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_ECC_SCHEME(value.sign, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.p, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.a, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.b, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.g_x, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.g_y, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.n, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.h, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ALGORITHM_DETAIL_ECC(
|
|
std::string* buffer,
|
|
TPMS_ALGORITHM_DETAIL_ECC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM_ECC_CURVE(
|
|
buffer,
|
|
&value->curve_id,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->key_size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_KDF_SCHEME(
|
|
buffer,
|
|
&value->kdf,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_ECC_SCHEME(
|
|
buffer,
|
|
&value->sign,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->p,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->a,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->b,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->g_x,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->g_y,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->n,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->h,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SIGNATURE_RSASSA(
|
|
const TPMS_SIGNATURE_RSASSA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.sig, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SIGNATURE_RSASSA(
|
|
std::string* buffer,
|
|
TPMS_SIGNATURE_RSASSA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
buffer,
|
|
&value->sig,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SIGNATURE_RSAPSS(
|
|
const TPMS_SIGNATURE_RSAPSS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.sig, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SIGNATURE_RSAPSS(
|
|
std::string* buffer,
|
|
TPMS_SIGNATURE_RSAPSS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
buffer,
|
|
&value->sig,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_SIGNATURE_ECDSA(
|
|
const TPMS_SIGNATURE_ECDSA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.signature_r, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.signature_s, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_SIGNATURE_ECDSA(
|
|
std::string* buffer,
|
|
TPMS_SIGNATURE_ECDSA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->signature_r,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->signature_s,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SIGNATURE(
|
|
const TPMU_SIGNATURE& value,
|
|
TPMI_ALG_SIG_SCHEME selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Serialize_TPMT_HA(value.hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecschnorr, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Serialize_TPMS_SIGNATURE_RSAPSS(value.rsapss, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecdaa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Serialize_TPMS_SIGNATURE_RSASSA(value.rsassa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Serialize_TPMS_SIGNATURE_ECDSA(value.sm2, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecdsa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SIGNATURE(
|
|
std::string* buffer,
|
|
TPMI_ALG_SIG_SCHEME selector,
|
|
TPMU_SIGNATURE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_HMAC) {
|
|
result = Parse_TPMT_HA(
|
|
buffer,
|
|
&value->hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECSCHNORR) {
|
|
result = Parse_TPMS_SIGNATURE_ECDSA(
|
|
buffer,
|
|
&value->ecschnorr,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSAPSS) {
|
|
result = Parse_TPMS_SIGNATURE_RSAPSS(
|
|
buffer,
|
|
&value->rsapss,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDAA) {
|
|
result = Parse_TPMS_SIGNATURE_ECDSA(
|
|
buffer,
|
|
&value->ecdaa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSASSA) {
|
|
result = Parse_TPMS_SIGNATURE_RSASSA(
|
|
buffer,
|
|
&value->rsassa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SM2) {
|
|
result = Parse_TPMS_SIGNATURE_ECDSA(
|
|
buffer,
|
|
&value->sm2,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECDSA) {
|
|
result = Parse_TPMS_SIGNATURE_ECDSA(
|
|
buffer,
|
|
&value->ecdsa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_NULL) {
|
|
// Do nothing.
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_SIGNATURE(
|
|
const TPMT_SIGNATURE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_SIG_SCHEME(value.sig_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SIGNATURE(
|
|
value.signature,
|
|
value.sig_alg,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_SIGNATURE(
|
|
std::string* buffer,
|
|
TPMT_SIGNATURE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_SIG_SCHEME(
|
|
buffer,
|
|
&value->sig_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SIGNATURE(
|
|
buffer,
|
|
value->sig_alg,
|
|
&value->signature,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_ENCRYPTED_SECRET(
|
|
const TPM2B_ENCRYPTED_SECRET& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.secret) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.secret[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_ENCRYPTED_SECRET(
|
|
std::string* buffer,
|
|
TPM2B_ENCRYPTED_SECRET* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->secret) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->secret[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_ENCRYPTED_SECRET Make_TPM2B_ENCRYPTED_SECRET(
|
|
const std::string& bytes) {
|
|
TPM2B_ENCRYPTED_SECRET tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.secret));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_ENCRYPTED_SECRET));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.secret, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_ENCRYPTED_SECRET(
|
|
const TPM2B_ENCRYPTED_SECRET& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.secret);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_KEYEDHASH_PARMS(
|
|
const TPMS_KEYEDHASH_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMT_KEYEDHASH_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_KEYEDHASH_PARMS(
|
|
std::string* buffer,
|
|
TPMS_KEYEDHASH_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMT_KEYEDHASH_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ASYM_PARMS(
|
|
const TPMS_ASYM_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_ASYM_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ASYM_PARMS(
|
|
std::string* buffer,
|
|
TPMS_ASYM_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMT_SYM_DEF_OBJECT(
|
|
buffer,
|
|
&value->symmetric,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_ASYM_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_RSA_PARMS(
|
|
const TPMS_RSA_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_RSA_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_RSA_KEY_BITS(value.key_bits, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT32(value.exponent, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_RSA_PARMS(
|
|
std::string* buffer,
|
|
TPMS_RSA_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMT_SYM_DEF_OBJECT(
|
|
buffer,
|
|
&value->symmetric,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_RSA_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_RSA_KEY_BITS(
|
|
buffer,
|
|
&value->key_bits,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT32(
|
|
buffer,
|
|
&value->exponent,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_ECC_PARMS(
|
|
const TPMS_ECC_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_ECC_SCHEME(value.scheme, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_ECC_CURVE(value.curve_id, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_KDF_SCHEME(value.kdf, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_ECC_PARMS(
|
|
std::string* buffer,
|
|
TPMS_ECC_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMT_SYM_DEF_OBJECT(
|
|
buffer,
|
|
&value->symmetric,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_ECC_SCHEME(
|
|
buffer,
|
|
&value->scheme,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_ECC_CURVE(
|
|
buffer,
|
|
&value->curve_id,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_KDF_SCHEME(
|
|
buffer,
|
|
&value->kdf,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_PUBLIC_PARMS(
|
|
const TPMU_PUBLIC_PARMS& value,
|
|
TPMI_ALG_PUBLIC selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Serialize_TPMS_KEYEDHASH_PARMS(value.keyed_hash_detail, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Serialize_TPMS_RSA_PARMS(value.rsa_detail, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Serialize_TPMS_SYMCIPHER_PARMS(value.sym_detail, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Serialize_TPMS_ECC_PARMS(value.ecc_detail, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_PUBLIC_PARMS(
|
|
std::string* buffer,
|
|
TPMI_ALG_PUBLIC selector,
|
|
TPMU_PUBLIC_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Parse_TPMS_KEYEDHASH_PARMS(
|
|
buffer,
|
|
&value->keyed_hash_detail,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Parse_TPMS_RSA_PARMS(
|
|
buffer,
|
|
&value->rsa_detail,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Parse_TPMS_SYMCIPHER_PARMS(
|
|
buffer,
|
|
&value->sym_detail,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Parse_TPMS_ECC_PARMS(
|
|
buffer,
|
|
&value->ecc_detail,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_PUBLIC_PARMS(
|
|
const TPMT_PUBLIC_PARMS& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_PUBLIC(value.type, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_PUBLIC_PARMS(
|
|
value.parameters,
|
|
value.type,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_PUBLIC_PARMS(
|
|
std::string* buffer,
|
|
TPMT_PUBLIC_PARMS* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_PUBLIC(
|
|
buffer,
|
|
&value->type,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_PUBLIC_PARMS(
|
|
buffer,
|
|
value->type,
|
|
&value->parameters,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_PUBLIC_ID(
|
|
const TPMU_PUBLIC_ID& value,
|
|
TPMI_ALG_PUBLIC selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Serialize_TPM2B_DIGEST(value.keyed_hash, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.rsa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Serialize_TPM2B_DIGEST(value.sym, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Serialize_TPMS_ECC_POINT(value.ecc, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_PUBLIC_ID(
|
|
std::string* buffer,
|
|
TPMI_ALG_PUBLIC selector,
|
|
TPMU_PUBLIC_ID* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->keyed_hash,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
buffer,
|
|
&value->rsa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->sym,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Parse_TPMS_ECC_POINT(
|
|
buffer,
|
|
&value->ecc,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_PUBLIC(
|
|
const TPMT_PUBLIC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_PUBLIC(value.type, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.name_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_OBJECT(value.object_attributes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.auth_policy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_PUBLIC_PARMS(
|
|
value.parameters,
|
|
value.type,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_PUBLIC_ID(
|
|
value.unique,
|
|
value.type,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_PUBLIC(
|
|
std::string* buffer,
|
|
TPMT_PUBLIC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_PUBLIC(
|
|
buffer,
|
|
&value->type,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->name_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_OBJECT(
|
|
buffer,
|
|
&value->object_attributes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->auth_policy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_PUBLIC_PARMS(
|
|
buffer,
|
|
value->type,
|
|
&value->parameters,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_PUBLIC_ID(
|
|
buffer,
|
|
value->type,
|
|
&value->unique,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_PUBLIC(
|
|
const TPM2B_PUBLIC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMT_PUBLIC(value.public_area, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_PUBLIC(
|
|
std::string* buffer,
|
|
TPM2B_PUBLIC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_PUBLIC(
|
|
buffer,
|
|
&value->public_area,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_PUBLIC Make_TPM2B_PUBLIC(
|
|
const TPMT_PUBLIC& inner) {
|
|
TPM2B_PUBLIC tpm2b;
|
|
tpm2b.size = sizeof(TPMT_PUBLIC);
|
|
tpm2b.public_area = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_PRIVATE_VENDOR_SPECIFIC(
|
|
const TPM2B_PRIVATE_VENDOR_SPECIFIC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_PRIVATE_VENDOR_SPECIFIC(
|
|
std::string* buffer,
|
|
TPM2B_PRIVATE_VENDOR_SPECIFIC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_PRIVATE_VENDOR_SPECIFIC Make_TPM2B_PRIVATE_VENDOR_SPECIFIC(
|
|
const std::string& bytes) {
|
|
TPM2B_PRIVATE_VENDOR_SPECIFIC tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE_VENDOR_SPECIFIC));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_PRIVATE_VENDOR_SPECIFIC(
|
|
const TPM2B_PRIVATE_VENDOR_SPECIFIC& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMU_SENSITIVE_COMPOSITE(
|
|
const TPMU_SENSITIVE_COMPOSITE& value,
|
|
TPMI_ALG_PUBLIC selector,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Serialize_TPM2B_SENSITIVE_DATA(value.bits, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Serialize_TPM2B_PRIVATE_KEY_RSA(value.rsa, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Serialize_TPM2B_SYM_KEY(value.sym, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Serialize_TPM2B_ECC_PARAMETER(value.ecc, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMU_SENSITIVE_COMPOSITE(
|
|
std::string* buffer,
|
|
TPMI_ALG_PUBLIC selector,
|
|
TPMU_SENSITIVE_COMPOSITE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
if (selector == TPM_ALG_KEYEDHASH) {
|
|
result = Parse_TPM2B_SENSITIVE_DATA(
|
|
buffer,
|
|
&value->bits,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_RSA) {
|
|
result = Parse_TPM2B_PRIVATE_KEY_RSA(
|
|
buffer,
|
|
&value->rsa,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_SYMCIPHER) {
|
|
result = Parse_TPM2B_SYM_KEY(
|
|
buffer,
|
|
&value->sym,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (selector == TPM_ALG_ECC) {
|
|
result = Parse_TPM2B_ECC_PARAMETER(
|
|
buffer,
|
|
&value->ecc,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMT_SENSITIVE(
|
|
const TPMT_SENSITIVE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_ALG_PUBLIC(value.sensitive_type, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_AUTH(value.auth_value, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.seed_value, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMU_SENSITIVE_COMPOSITE(
|
|
value.sensitive,
|
|
value.sensitive_type,
|
|
buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMT_SENSITIVE(
|
|
std::string* buffer,
|
|
TPMT_SENSITIVE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_ALG_PUBLIC(
|
|
buffer,
|
|
&value->sensitive_type,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_AUTH(
|
|
buffer,
|
|
&value->auth_value,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->seed_value,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMU_SENSITIVE_COMPOSITE(
|
|
buffer,
|
|
value->sensitive_type,
|
|
&value->sensitive,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_SENSITIVE(
|
|
const TPM2B_SENSITIVE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMT_SENSITIVE(value.sensitive_area, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_SENSITIVE(
|
|
std::string* buffer,
|
|
TPM2B_SENSITIVE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_SENSITIVE(
|
|
buffer,
|
|
&value->sensitive_area,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_SENSITIVE Make_TPM2B_SENSITIVE(
|
|
const TPMT_SENSITIVE& inner) {
|
|
TPM2B_SENSITIVE tpm2b;
|
|
tpm2b.size = sizeof(TPMT_SENSITIVE);
|
|
tpm2b.sensitive_area = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Serialize__PRIVATE(
|
|
const _PRIVATE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.integrity_outer, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.integrity_inner, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMT_SENSITIVE(value.sensitive, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse__PRIVATE(
|
|
std::string* buffer,
|
|
_PRIVATE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->integrity_outer,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->integrity_inner,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMT_SENSITIVE(
|
|
buffer,
|
|
&value->sensitive,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_PRIVATE(
|
|
const TPM2B_PRIVATE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_PRIVATE(
|
|
std::string* buffer,
|
|
TPM2B_PRIVATE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_PRIVATE Make_TPM2B_PRIVATE(
|
|
const std::string& bytes) {
|
|
TPM2B_PRIVATE tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_PRIVATE(
|
|
const TPM2B_PRIVATE& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize__ID_OBJECT(
|
|
const _ID_OBJECT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.integrity_hmac, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.enc_identity, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse__ID_OBJECT(
|
|
std::string* buffer,
|
|
_ID_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->integrity_hmac,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->enc_identity,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_ID_OBJECT(
|
|
const TPM2B_ID_OBJECT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.credential) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.credential[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_ID_OBJECT(
|
|
std::string* buffer,
|
|
TPM2B_ID_OBJECT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->credential) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->credential[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_ID_OBJECT Make_TPM2B_ID_OBJECT(
|
|
const std::string& bytes) {
|
|
TPM2B_ID_OBJECT tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.credential));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_ID_OBJECT));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.credential, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_ID_OBJECT(
|
|
const TPM2B_ID_OBJECT& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.credential);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_NV_PUBLIC(
|
|
const TPMS_NV_PUBLIC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPMI_RH_NV_INDEX(value.nv_index, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_ALG_HASH(value.name_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_NV(value.attributes, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.auth_policy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_UINT16(value.data_size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_NV_PUBLIC(
|
|
std::string* buffer,
|
|
TPMS_NV_PUBLIC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPMI_RH_NV_INDEX(
|
|
buffer,
|
|
&value->nv_index,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_ALG_HASH(
|
|
buffer,
|
|
&value->name_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_NV(
|
|
buffer,
|
|
&value->attributes,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->auth_policy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->data_size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_NV_PUBLIC(
|
|
const TPM2B_NV_PUBLIC& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMS_NV_PUBLIC(value.nv_public, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_NV_PUBLIC(
|
|
std::string* buffer,
|
|
TPM2B_NV_PUBLIC* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_NV_PUBLIC(
|
|
buffer,
|
|
&value->nv_public,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_NV_PUBLIC Make_TPM2B_NV_PUBLIC(
|
|
const TPMS_NV_PUBLIC& inner) {
|
|
TPM2B_NV_PUBLIC tpm2b;
|
|
tpm2b.size = sizeof(TPMS_NV_PUBLIC);
|
|
tpm2b.nv_public = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_CONTEXT_SENSITIVE(
|
|
const TPM2B_CONTEXT_SENSITIVE& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_CONTEXT_SENSITIVE(
|
|
std::string* buffer,
|
|
TPM2B_CONTEXT_SENSITIVE* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_CONTEXT_SENSITIVE Make_TPM2B_CONTEXT_SENSITIVE(
|
|
const std::string& bytes) {
|
|
TPM2B_CONTEXT_SENSITIVE tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_CONTEXT_SENSITIVE));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_CONTEXT_SENSITIVE(
|
|
const TPM2B_CONTEXT_SENSITIVE& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CONTEXT_DATA(
|
|
const TPMS_CONTEXT_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.integrity, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_CONTEXT_SENSITIVE(value.encrypted, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CONTEXT_DATA(
|
|
std::string* buffer,
|
|
TPMS_CONTEXT_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->integrity,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_CONTEXT_SENSITIVE(
|
|
buffer,
|
|
&value->encrypted,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_CONTEXT_DATA(
|
|
const TPM2B_CONTEXT_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT16(value.size, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value.buffer) < value.size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value.size; ++i) {
|
|
result = Serialize_BYTE(value.buffer[i], buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_CONTEXT_DATA(
|
|
std::string* buffer,
|
|
TPM2B_CONTEXT_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (arraysize(value->buffer) < value->size) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
for (uint32_t i = 0; i < value->size; ++i) {
|
|
result = Parse_BYTE(
|
|
buffer,
|
|
&value->buffer[i],
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_CONTEXT_DATA Make_TPM2B_CONTEXT_DATA(
|
|
const std::string& bytes) {
|
|
TPM2B_CONTEXT_DATA tpm2b;
|
|
CHECK(bytes.size() <= sizeof(tpm2b.buffer));
|
|
memset(&tpm2b, 0, sizeof(TPM2B_CONTEXT_DATA));
|
|
tpm2b.size = bytes.size();
|
|
memcpy(tpm2b.buffer, bytes.data(), bytes.size());
|
|
return tpm2b;
|
|
}
|
|
|
|
std::string StringFrom_TPM2B_CONTEXT_DATA(
|
|
const TPM2B_CONTEXT_DATA& tpm2b) {
|
|
const char* char_buffer = reinterpret_cast<const char*>(
|
|
tpm2b.buffer);
|
|
return std::string(char_buffer, tpm2b.size);
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CONTEXT(
|
|
const TPMS_CONTEXT& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_UINT64(value.sequence, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_DH_CONTEXT(value.saved_handle, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_CONTEXT_DATA(value.context_blob, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CONTEXT(
|
|
std::string* buffer,
|
|
TPMS_CONTEXT* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT64(
|
|
buffer,
|
|
&value->sequence,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_DH_CONTEXT(
|
|
buffer,
|
|
&value->saved_handle,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMI_RH_HIERARCHY(
|
|
buffer,
|
|
&value->hierarchy,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_CONTEXT_DATA(
|
|
buffer,
|
|
&value->context_blob,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPMS_CREATION_DATA(
|
|
const TPMS_CREATION_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Serialize_TPML_PCR_SELECTION(value.pcr_select, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DIGEST(value.pcr_digest, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPMA_LOCALITY(value.locality, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM_ALG_ID(value.parent_name_alg, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_NAME(value.parent_name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_NAME(value.parent_qualified_name, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Serialize_TPM2B_DATA(value.outside_info, buffer);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPMS_CREATION_DATA(
|
|
std::string* buffer,
|
|
TPMS_CREATION_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_TPML_PCR_SELECTION(
|
|
buffer,
|
|
&value->pcr_select,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DIGEST(
|
|
buffer,
|
|
&value->pcr_digest,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMA_LOCALITY(
|
|
buffer,
|
|
&value->locality,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM_ALG_ID(
|
|
buffer,
|
|
&value->parent_name_alg,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->parent_name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_NAME(
|
|
buffer,
|
|
&value->parent_qualified_name,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPM2B_DATA(
|
|
buffer,
|
|
&value->outside_info,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Serialize_TPM2B_CREATION_DATA(
|
|
const TPM2B_CREATION_DATA& value,
|
|
std::string* buffer) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
std::string field_bytes;
|
|
result = Serialize_TPMS_CREATION_DATA(value.creation_data, &field_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
std::string size_bytes;
|
|
result = Serialize_UINT16(field_bytes.size(), &size_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
buffer->append(size_bytes + field_bytes);
|
|
return result;
|
|
}
|
|
|
|
TPM_RC Parse_TPM2B_CREATION_DATA(
|
|
std::string* buffer,
|
|
TPM2B_CREATION_DATA* value,
|
|
std::string* value_bytes) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
VLOG(3) << __func__;
|
|
|
|
result = Parse_UINT16(
|
|
buffer,
|
|
&value->size,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
result = Parse_TPMS_CREATION_DATA(
|
|
buffer,
|
|
&value->creation_data,
|
|
value_bytes);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TPM2B_CREATION_DATA Make_TPM2B_CREATION_DATA(
|
|
const TPMS_CREATION_DATA& inner) {
|
|
TPM2B_CREATION_DATA tpm2b;
|
|
tpm2b.size = sizeof(TPMS_CREATION_DATA);
|
|
tpm2b.creation_data = inner;
|
|
return tpm2b;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Startup(
|
|
const TPM_SU& startup_type,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Startup;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string startup_type_bytes;
|
|
rc = Serialize_TPM_SU(
|
|
startup_type,
|
|
&startup_type_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(startup_type_bytes.data(),
|
|
startup_type_bytes.size());
|
|
parameter_section_bytes += startup_type_bytes;
|
|
command_size += startup_type_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Startup(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Startup;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void StartupErrorCallback(
|
|
const Tpm::StartupResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void StartupResponseParser(
|
|
const Tpm::StartupResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StartupErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_Startup(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::Startup(
|
|
const TPM_SU& startup_type,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const StartupResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StartupErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(StartupResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Startup(
|
|
startup_type,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::StartupSync(
|
|
const TPM_SU& startup_type,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Startup(
|
|
startup_type,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Startup(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Shutdown(
|
|
const TPM_SU& shutdown_type,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Shutdown;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string shutdown_type_bytes;
|
|
rc = Serialize_TPM_SU(
|
|
shutdown_type,
|
|
&shutdown_type_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(shutdown_type_bytes.data(),
|
|
shutdown_type_bytes.size());
|
|
parameter_section_bytes += shutdown_type_bytes;
|
|
command_size += shutdown_type_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Shutdown(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Shutdown;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ShutdownErrorCallback(
|
|
const Tpm::ShutdownResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ShutdownResponseParser(
|
|
const Tpm::ShutdownResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ShutdownErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_Shutdown(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::Shutdown(
|
|
const TPM_SU& shutdown_type,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ShutdownResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ShutdownErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ShutdownResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Shutdown(
|
|
shutdown_type,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ShutdownSync(
|
|
const TPM_SU& shutdown_type,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Shutdown(
|
|
shutdown_type,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Shutdown(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SelfTest(
|
|
const TPMI_YES_NO& full_test,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SelfTest;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string full_test_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
full_test,
|
|
&full_test_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(full_test_bytes.data(),
|
|
full_test_bytes.size());
|
|
parameter_section_bytes += full_test_bytes;
|
|
command_size += full_test_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SelfTest(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SelfTest;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SelfTestErrorCallback(
|
|
const Tpm::SelfTestResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void SelfTestResponseParser(
|
|
const Tpm::SelfTestResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SelfTestErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_SelfTest(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::SelfTest(
|
|
const TPMI_YES_NO& full_test,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SelfTestResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SelfTestErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SelfTestResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SelfTest(
|
|
full_test,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SelfTestSync(
|
|
const TPMI_YES_NO& full_test,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SelfTest(
|
|
full_test,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SelfTest(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_IncrementalSelfTest(
|
|
const TPML_ALG& to_test,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_IncrementalSelfTest;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string to_test_bytes;
|
|
rc = Serialize_TPML_ALG(
|
|
to_test,
|
|
&to_test_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(to_test_bytes.data(),
|
|
to_test_bytes.size());
|
|
parameter_section_bytes += to_test_bytes;
|
|
command_size += to_test_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_IncrementalSelfTest(
|
|
const std::string& response,
|
|
TPML_ALG* to_do_list,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_IncrementalSelfTest;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string to_do_list_bytes;
|
|
rc = Parse_TPML_ALG(
|
|
&buffer,
|
|
to_do_list,
|
|
&to_do_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void IncrementalSelfTestErrorCallback(
|
|
const Tpm::IncrementalSelfTestResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPML_ALG());
|
|
}
|
|
|
|
void IncrementalSelfTestResponseParser(
|
|
const Tpm::IncrementalSelfTestResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(IncrementalSelfTestErrorCallback, callback);
|
|
TPML_ALG to_do_list;
|
|
TPM_RC rc = Tpm::ParseResponse_IncrementalSelfTest(
|
|
response,
|
|
&to_do_list,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
to_do_list);
|
|
}
|
|
|
|
void Tpm::IncrementalSelfTest(
|
|
const TPML_ALG& to_test,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const IncrementalSelfTestResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(IncrementalSelfTestErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(IncrementalSelfTestResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_IncrementalSelfTest(
|
|
to_test,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::IncrementalSelfTestSync(
|
|
const TPML_ALG& to_test,
|
|
TPML_ALG* to_do_list,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_IncrementalSelfTest(
|
|
to_test,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_IncrementalSelfTest(
|
|
response,
|
|
to_do_list,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetTestResult(
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetTestResult;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetTestResult(
|
|
const std::string& response,
|
|
TPM2B_MAX_BUFFER* out_data,
|
|
TPM_RC* test_result,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetTestResult;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_data_bytes;
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&buffer,
|
|
out_data,
|
|
&out_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string test_result_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
test_result,
|
|
&test_result_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&out_data_bytes,
|
|
out_data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetTestResultErrorCallback(
|
|
const Tpm::GetTestResultResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_MAX_BUFFER(),
|
|
TPM_RC());
|
|
}
|
|
|
|
void GetTestResultResponseParser(
|
|
const Tpm::GetTestResultResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetTestResultErrorCallback, callback);
|
|
TPM2B_MAX_BUFFER out_data;
|
|
TPM_RC test_result;
|
|
TPM_RC rc = Tpm::ParseResponse_GetTestResult(
|
|
response,
|
|
&out_data,
|
|
&test_result,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_data,
|
|
test_result);
|
|
}
|
|
|
|
void Tpm::GetTestResult(
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetTestResultResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetTestResultErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetTestResultResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetTestResult(
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetTestResultSync(
|
|
TPM2B_MAX_BUFFER* out_data,
|
|
TPM_RC* test_result,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetTestResult(
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetTestResult(
|
|
response,
|
|
out_data,
|
|
test_result,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_StartAuthSession(
|
|
const TPMI_DH_OBJECT& tpm_key,
|
|
const std::string& tpm_key_name,
|
|
const TPMI_DH_ENTITY& bind,
|
|
const std::string& bind_name,
|
|
const TPM2B_NONCE& nonce_caller,
|
|
const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
|
|
const TPM_SE& session_type,
|
|
const TPMT_SYM_DEF& symmetric,
|
|
const TPMI_ALG_HASH& auth_hash,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_StartAuthSession;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string tpm_key_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
tpm_key,
|
|
&tpm_key_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string bind_bytes;
|
|
rc = Serialize_TPMI_DH_ENTITY(
|
|
bind,
|
|
&bind_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nonce_caller_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
nonce_caller,
|
|
&nonce_caller_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string encrypted_salt_bytes;
|
|
rc = Serialize_TPM2B_ENCRYPTED_SECRET(
|
|
encrypted_salt,
|
|
&encrypted_salt_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string session_type_bytes;
|
|
rc = Serialize_TPM_SE(
|
|
session_type,
|
|
&session_type_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string symmetric_bytes;
|
|
rc = Serialize_TPMT_SYM_DEF(
|
|
symmetric,
|
|
&symmetric_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_hash_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
auth_hash,
|
|
&auth_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = nonce_caller_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
nonce_caller_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(tpm_key_name.data(),
|
|
tpm_key_name.size());
|
|
handle_section_bytes += tpm_key_bytes;
|
|
command_size += tpm_key_bytes.size();
|
|
hash->Update(bind_name.data(),
|
|
bind_name.size());
|
|
handle_section_bytes += bind_bytes;
|
|
command_size += bind_bytes.size();
|
|
hash->Update(nonce_caller_bytes.data(),
|
|
nonce_caller_bytes.size());
|
|
parameter_section_bytes += nonce_caller_bytes;
|
|
command_size += nonce_caller_bytes.size();
|
|
hash->Update(encrypted_salt_bytes.data(),
|
|
encrypted_salt_bytes.size());
|
|
parameter_section_bytes += encrypted_salt_bytes;
|
|
command_size += encrypted_salt_bytes.size();
|
|
hash->Update(session_type_bytes.data(),
|
|
session_type_bytes.size());
|
|
parameter_section_bytes += session_type_bytes;
|
|
command_size += session_type_bytes.size();
|
|
hash->Update(symmetric_bytes.data(),
|
|
symmetric_bytes.size());
|
|
parameter_section_bytes += symmetric_bytes;
|
|
command_size += symmetric_bytes.size();
|
|
hash->Update(auth_hash_bytes.data(),
|
|
auth_hash_bytes.size());
|
|
parameter_section_bytes += auth_hash_bytes;
|
|
command_size += auth_hash_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_StartAuthSession(
|
|
const std::string& response,
|
|
TPMI_SH_AUTH_SESSION* session_handle,
|
|
TPM2B_NONCE* nonce_tpm,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string session_handle_bytes;
|
|
rc = Parse_TPMI_SH_AUTH_SESSION(
|
|
&buffer,
|
|
session_handle,
|
|
&session_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_StartAuthSession;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string nonce_tpm_bytes;
|
|
rc = Parse_TPM2B_NONCE(
|
|
&buffer,
|
|
nonce_tpm,
|
|
&nonce_tpm_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = nonce_tpm_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
nonce_tpm_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_NONCE(
|
|
&nonce_tpm_bytes,
|
|
nonce_tpm,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void StartAuthSessionErrorCallback(
|
|
const Tpm::StartAuthSessionResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_SH_AUTH_SESSION(),
|
|
TPM2B_NONCE());
|
|
}
|
|
|
|
void StartAuthSessionResponseParser(
|
|
const Tpm::StartAuthSessionResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StartAuthSessionErrorCallback, callback);
|
|
TPMI_SH_AUTH_SESSION session_handle;
|
|
TPM2B_NONCE nonce_tpm;
|
|
TPM_RC rc = Tpm::ParseResponse_StartAuthSession(
|
|
response,
|
|
&session_handle,
|
|
&nonce_tpm,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
session_handle,
|
|
nonce_tpm);
|
|
}
|
|
|
|
void Tpm::StartAuthSession(
|
|
const TPMI_DH_OBJECT& tpm_key,
|
|
const std::string& tpm_key_name,
|
|
const TPMI_DH_ENTITY& bind,
|
|
const std::string& bind_name,
|
|
const TPM2B_NONCE& nonce_caller,
|
|
const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
|
|
const TPM_SE& session_type,
|
|
const TPMT_SYM_DEF& symmetric,
|
|
const TPMI_ALG_HASH& auth_hash,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const StartAuthSessionResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StartAuthSessionErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(StartAuthSessionResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_StartAuthSession(
|
|
tpm_key,
|
|
tpm_key_name,
|
|
bind,
|
|
bind_name,
|
|
nonce_caller,
|
|
encrypted_salt,
|
|
session_type,
|
|
symmetric,
|
|
auth_hash,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::StartAuthSessionSync(
|
|
const TPMI_DH_OBJECT& tpm_key,
|
|
const std::string& tpm_key_name,
|
|
const TPMI_DH_ENTITY& bind,
|
|
const std::string& bind_name,
|
|
const TPM2B_NONCE& nonce_caller,
|
|
const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
|
|
const TPM_SE& session_type,
|
|
const TPMT_SYM_DEF& symmetric,
|
|
const TPMI_ALG_HASH& auth_hash,
|
|
TPMI_SH_AUTH_SESSION* session_handle,
|
|
TPM2B_NONCE* nonce_tpm,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_StartAuthSession(
|
|
tpm_key,
|
|
tpm_key_name,
|
|
bind,
|
|
bind_name,
|
|
nonce_caller,
|
|
encrypted_salt,
|
|
session_type,
|
|
symmetric,
|
|
auth_hash,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_StartAuthSession(
|
|
response,
|
|
session_handle,
|
|
nonce_tpm,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyRestart(
|
|
const TPMI_SH_POLICY& session_handle,
|
|
const std::string& session_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyRestart;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string session_handle_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
session_handle,
|
|
&session_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(session_handle_name.data(),
|
|
session_handle_name.size());
|
|
handle_section_bytes += session_handle_bytes;
|
|
command_size += session_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyRestart(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyRestart;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyRestartErrorCallback(
|
|
const Tpm::PolicyRestartResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyRestartResponseParser(
|
|
const Tpm::PolicyRestartResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyRestartErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyRestart(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyRestart(
|
|
const TPMI_SH_POLICY& session_handle,
|
|
const std::string& session_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyRestartResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyRestartErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyRestartResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyRestart(
|
|
session_handle,
|
|
session_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyRestartSync(
|
|
const TPMI_SH_POLICY& session_handle,
|
|
const std::string& session_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyRestart(
|
|
session_handle,
|
|
session_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyRestart(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Create(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Create;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string parent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
parent_handle,
|
|
&parent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_sensitive_bytes;
|
|
rc = Serialize_TPM2B_SENSITIVE_CREATE(
|
|
in_sensitive,
|
|
&in_sensitive_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_public_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC(
|
|
in_public,
|
|
&in_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string outside_info_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
outside_info,
|
|
&outside_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_pcr_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
creation_pcr,
|
|
&creation_pcr_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_sensitive_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_sensitive_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(parent_handle_name.data(),
|
|
parent_handle_name.size());
|
|
handle_section_bytes += parent_handle_bytes;
|
|
command_size += parent_handle_bytes.size();
|
|
hash->Update(in_sensitive_bytes.data(),
|
|
in_sensitive_bytes.size());
|
|
parameter_section_bytes += in_sensitive_bytes;
|
|
command_size += in_sensitive_bytes.size();
|
|
hash->Update(in_public_bytes.data(),
|
|
in_public_bytes.size());
|
|
parameter_section_bytes += in_public_bytes;
|
|
command_size += in_public_bytes.size();
|
|
hash->Update(outside_info_bytes.data(),
|
|
outside_info_bytes.size());
|
|
parameter_section_bytes += outside_info_bytes;
|
|
command_size += outside_info_bytes.size();
|
|
hash->Update(creation_pcr_bytes.data(),
|
|
creation_pcr_bytes.size());
|
|
parameter_section_bytes += creation_pcr_bytes;
|
|
command_size += creation_pcr_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Create(
|
|
const std::string& response,
|
|
TPM2B_PRIVATE* out_private,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_CREATION_DATA* creation_data,
|
|
TPM2B_DIGEST* creation_hash,
|
|
TPMT_TK_CREATION* creation_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Create;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_private_bytes;
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&buffer,
|
|
out_private,
|
|
&out_private_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string out_public_bytes;
|
|
rc = Parse_TPM2B_PUBLIC(
|
|
&buffer,
|
|
out_public,
|
|
&out_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_data_bytes;
|
|
rc = Parse_TPM2B_CREATION_DATA(
|
|
&buffer,
|
|
creation_data,
|
|
&creation_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_hash_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
creation_hash,
|
|
&creation_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_ticket_bytes;
|
|
rc = Parse_TPMT_TK_CREATION(
|
|
&buffer,
|
|
creation_ticket,
|
|
&creation_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_private_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_private_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&out_private_bytes,
|
|
out_private,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void CreateErrorCallback(
|
|
const Tpm::CreateResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PRIVATE(),
|
|
TPM2B_PUBLIC(),
|
|
TPM2B_CREATION_DATA(),
|
|
TPM2B_DIGEST(),
|
|
TPMT_TK_CREATION());
|
|
}
|
|
|
|
void CreateResponseParser(
|
|
const Tpm::CreateResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CreateErrorCallback, callback);
|
|
TPM2B_PRIVATE out_private;
|
|
TPM2B_PUBLIC out_public;
|
|
TPM2B_CREATION_DATA creation_data;
|
|
TPM2B_DIGEST creation_hash;
|
|
TPMT_TK_CREATION creation_ticket;
|
|
TPM_RC rc = Tpm::ParseResponse_Create(
|
|
response,
|
|
&out_private,
|
|
&out_public,
|
|
&creation_data,
|
|
&creation_hash,
|
|
&creation_ticket,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_private,
|
|
out_public,
|
|
creation_data,
|
|
creation_hash,
|
|
creation_ticket);
|
|
}
|
|
|
|
void Tpm::Create(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const CreateResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CreateErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(CreateResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Create(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
in_sensitive,
|
|
in_public,
|
|
outside_info,
|
|
creation_pcr,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::CreateSync(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
TPM2B_PRIVATE* out_private,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_CREATION_DATA* creation_data,
|
|
TPM2B_DIGEST* creation_hash,
|
|
TPMT_TK_CREATION* creation_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Create(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
in_sensitive,
|
|
in_public,
|
|
outside_info,
|
|
creation_pcr,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Create(
|
|
response,
|
|
out_private,
|
|
out_public,
|
|
creation_data,
|
|
creation_hash,
|
|
creation_ticket,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Load(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_PRIVATE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Load;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string parent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
parent_handle,
|
|
&parent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_private_bytes;
|
|
rc = Serialize_TPM2B_PRIVATE(
|
|
in_private,
|
|
&in_private_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_public_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC(
|
|
in_public,
|
|
&in_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_private_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_private_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(parent_handle_name.data(),
|
|
parent_handle_name.size());
|
|
handle_section_bytes += parent_handle_bytes;
|
|
command_size += parent_handle_bytes.size();
|
|
hash->Update(in_private_bytes.data(),
|
|
in_private_bytes.size());
|
|
parameter_section_bytes += in_private_bytes;
|
|
command_size += in_private_bytes.size();
|
|
hash->Update(in_public_bytes.data(),
|
|
in_public_bytes.size());
|
|
parameter_section_bytes += in_public_bytes;
|
|
command_size += in_public_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Load(
|
|
const std::string& response,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Parse_TPM_HANDLE(
|
|
&buffer,
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Load;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
name,
|
|
&name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = name_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
name_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_NAME(
|
|
&name_bytes,
|
|
name,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void LoadErrorCallback(
|
|
const Tpm::LoadResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM_HANDLE(),
|
|
TPM2B_NAME());
|
|
}
|
|
|
|
void LoadResponseParser(
|
|
const Tpm::LoadResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(LoadErrorCallback, callback);
|
|
TPM_HANDLE object_handle;
|
|
TPM2B_NAME name;
|
|
TPM_RC rc = Tpm::ParseResponse_Load(
|
|
response,
|
|
&object_handle,
|
|
&name,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
object_handle,
|
|
name);
|
|
}
|
|
|
|
void Tpm::Load(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_PRIVATE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const LoadResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(LoadErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(LoadResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Load(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
in_private,
|
|
in_public,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::LoadSync(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_PRIVATE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Load(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
in_private,
|
|
in_public,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Load(
|
|
response,
|
|
object_handle,
|
|
name,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_LoadExternal(
|
|
const TPM2B_SENSITIVE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_LoadExternal;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_private_bytes;
|
|
rc = Serialize_TPM2B_SENSITIVE(
|
|
in_private,
|
|
&in_private_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_public_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC(
|
|
in_public,
|
|
&in_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hierarchy_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
hierarchy,
|
|
&hierarchy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_private_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_private_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(in_private_bytes.data(),
|
|
in_private_bytes.size());
|
|
parameter_section_bytes += in_private_bytes;
|
|
command_size += in_private_bytes.size();
|
|
hash->Update(in_public_bytes.data(),
|
|
in_public_bytes.size());
|
|
parameter_section_bytes += in_public_bytes;
|
|
command_size += in_public_bytes.size();
|
|
hash->Update(hierarchy_bytes.data(),
|
|
hierarchy_bytes.size());
|
|
parameter_section_bytes += hierarchy_bytes;
|
|
command_size += hierarchy_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_LoadExternal(
|
|
const std::string& response,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Parse_TPM_HANDLE(
|
|
&buffer,
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_LoadExternal;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
name,
|
|
&name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = name_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
name_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_NAME(
|
|
&name_bytes,
|
|
name,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void LoadExternalErrorCallback(
|
|
const Tpm::LoadExternalResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM_HANDLE(),
|
|
TPM2B_NAME());
|
|
}
|
|
|
|
void LoadExternalResponseParser(
|
|
const Tpm::LoadExternalResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(LoadExternalErrorCallback, callback);
|
|
TPM_HANDLE object_handle;
|
|
TPM2B_NAME name;
|
|
TPM_RC rc = Tpm::ParseResponse_LoadExternal(
|
|
response,
|
|
&object_handle,
|
|
&name,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
object_handle,
|
|
name);
|
|
}
|
|
|
|
void Tpm::LoadExternal(
|
|
const TPM2B_SENSITIVE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const LoadExternalResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(LoadExternalErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(LoadExternalResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_LoadExternal(
|
|
in_private,
|
|
in_public,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::LoadExternalSync(
|
|
const TPM2B_SENSITIVE& in_private,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_LoadExternal(
|
|
in_private,
|
|
in_public,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_LoadExternal(
|
|
response,
|
|
object_handle,
|
|
name,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ReadPublic(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ReadPublic;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ReadPublic(
|
|
const std::string& response,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_NAME* name,
|
|
TPM2B_NAME* qualified_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ReadPublic;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_public_bytes;
|
|
rc = Parse_TPM2B_PUBLIC(
|
|
&buffer,
|
|
out_public,
|
|
&out_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
name,
|
|
&name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualified_name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
qualified_name,
|
|
&qualified_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_public_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_public_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PUBLIC(
|
|
&out_public_bytes,
|
|
out_public,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ReadPublicErrorCallback(
|
|
const Tpm::ReadPublicResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PUBLIC(),
|
|
TPM2B_NAME(),
|
|
TPM2B_NAME());
|
|
}
|
|
|
|
void ReadPublicResponseParser(
|
|
const Tpm::ReadPublicResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ReadPublicErrorCallback, callback);
|
|
TPM2B_PUBLIC out_public;
|
|
TPM2B_NAME name;
|
|
TPM2B_NAME qualified_name;
|
|
TPM_RC rc = Tpm::ParseResponse_ReadPublic(
|
|
response,
|
|
&out_public,
|
|
&name,
|
|
&qualified_name,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_public,
|
|
name,
|
|
qualified_name);
|
|
}
|
|
|
|
void Tpm::ReadPublic(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ReadPublicResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ReadPublicErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ReadPublicResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ReadPublic(
|
|
object_handle,
|
|
object_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ReadPublicSync(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_NAME* name,
|
|
TPM2B_NAME* qualified_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ReadPublic(
|
|
object_handle,
|
|
object_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ReadPublic(
|
|
response,
|
|
out_public,
|
|
name,
|
|
qualified_name,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ActivateCredential(
|
|
const TPMI_DH_OBJECT& activate_handle,
|
|
const std::string& activate_handle_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ID_OBJECT& credential_blob,
|
|
const TPM2B_ENCRYPTED_SECRET& secret,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ActivateCredential;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string activate_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
activate_handle,
|
|
&activate_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string credential_blob_bytes;
|
|
rc = Serialize_TPM2B_ID_OBJECT(
|
|
credential_blob,
|
|
&credential_blob_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string secret_bytes;
|
|
rc = Serialize_TPM2B_ENCRYPTED_SECRET(
|
|
secret,
|
|
&secret_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = credential_blob_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
credential_blob_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(activate_handle_name.data(),
|
|
activate_handle_name.size());
|
|
handle_section_bytes += activate_handle_bytes;
|
|
command_size += activate_handle_bytes.size();
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(credential_blob_bytes.data(),
|
|
credential_blob_bytes.size());
|
|
parameter_section_bytes += credential_blob_bytes;
|
|
command_size += credential_blob_bytes.size();
|
|
hash->Update(secret_bytes.data(),
|
|
secret_bytes.size());
|
|
parameter_section_bytes += secret_bytes;
|
|
command_size += secret_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ActivateCredential(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* cert_info,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ActivateCredential;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string cert_info_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
cert_info,
|
|
&cert_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = cert_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
cert_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&cert_info_bytes,
|
|
cert_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ActivateCredentialErrorCallback(
|
|
const Tpm::ActivateCredentialResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST());
|
|
}
|
|
|
|
void ActivateCredentialResponseParser(
|
|
const Tpm::ActivateCredentialResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ActivateCredentialErrorCallback, callback);
|
|
TPM2B_DIGEST cert_info;
|
|
TPM_RC rc = Tpm::ParseResponse_ActivateCredential(
|
|
response,
|
|
&cert_info,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
cert_info);
|
|
}
|
|
|
|
void Tpm::ActivateCredential(
|
|
const TPMI_DH_OBJECT& activate_handle,
|
|
const std::string& activate_handle_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ID_OBJECT& credential_blob,
|
|
const TPM2B_ENCRYPTED_SECRET& secret,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ActivateCredentialResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ActivateCredentialErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ActivateCredentialResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ActivateCredential(
|
|
activate_handle,
|
|
activate_handle_name,
|
|
key_handle,
|
|
key_handle_name,
|
|
credential_blob,
|
|
secret,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ActivateCredentialSync(
|
|
const TPMI_DH_OBJECT& activate_handle,
|
|
const std::string& activate_handle_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ID_OBJECT& credential_blob,
|
|
const TPM2B_ENCRYPTED_SECRET& secret,
|
|
TPM2B_DIGEST* cert_info,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ActivateCredential(
|
|
activate_handle,
|
|
activate_handle_name,
|
|
key_handle,
|
|
key_handle_name,
|
|
credential_blob,
|
|
secret,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ActivateCredential(
|
|
response,
|
|
cert_info,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_MakeCredential(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_DIGEST& credential,
|
|
const TPM2B_NAME& object_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_MakeCredential;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
handle,
|
|
&handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string credential_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
credential,
|
|
&credential_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_name_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
object_name,
|
|
&object_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = credential_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
credential_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(handle_name.data(),
|
|
handle_name.size());
|
|
handle_section_bytes += handle_bytes;
|
|
command_size += handle_bytes.size();
|
|
hash->Update(credential_bytes.data(),
|
|
credential_bytes.size());
|
|
parameter_section_bytes += credential_bytes;
|
|
command_size += credential_bytes.size();
|
|
hash->Update(object_name_bytes.data(),
|
|
object_name_bytes.size());
|
|
parameter_section_bytes += object_name_bytes;
|
|
command_size += object_name_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_MakeCredential(
|
|
const std::string& response,
|
|
TPM2B_ID_OBJECT* credential_blob,
|
|
TPM2B_ENCRYPTED_SECRET* secret,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_MakeCredential;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string credential_blob_bytes;
|
|
rc = Parse_TPM2B_ID_OBJECT(
|
|
&buffer,
|
|
credential_blob,
|
|
&credential_blob_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string secret_bytes;
|
|
rc = Parse_TPM2B_ENCRYPTED_SECRET(
|
|
&buffer,
|
|
secret,
|
|
&secret_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = credential_blob_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
credential_blob_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ID_OBJECT(
|
|
&credential_blob_bytes,
|
|
credential_blob,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void MakeCredentialErrorCallback(
|
|
const Tpm::MakeCredentialResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ID_OBJECT(),
|
|
TPM2B_ENCRYPTED_SECRET());
|
|
}
|
|
|
|
void MakeCredentialResponseParser(
|
|
const Tpm::MakeCredentialResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(MakeCredentialErrorCallback, callback);
|
|
TPM2B_ID_OBJECT credential_blob;
|
|
TPM2B_ENCRYPTED_SECRET secret;
|
|
TPM_RC rc = Tpm::ParseResponse_MakeCredential(
|
|
response,
|
|
&credential_blob,
|
|
&secret,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
credential_blob,
|
|
secret);
|
|
}
|
|
|
|
void Tpm::MakeCredential(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_DIGEST& credential,
|
|
const TPM2B_NAME& object_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const MakeCredentialResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(MakeCredentialErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(MakeCredentialResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_MakeCredential(
|
|
handle,
|
|
handle_name,
|
|
credential,
|
|
object_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::MakeCredentialSync(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_DIGEST& credential,
|
|
const TPM2B_NAME& object_name,
|
|
TPM2B_ID_OBJECT* credential_blob,
|
|
TPM2B_ENCRYPTED_SECRET* secret,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_MakeCredential(
|
|
handle,
|
|
handle_name,
|
|
credential,
|
|
object_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_MakeCredential(
|
|
response,
|
|
credential_blob,
|
|
secret,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Unseal(
|
|
const TPMI_DH_OBJECT& item_handle,
|
|
const std::string& item_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Unseal;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string item_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
item_handle,
|
|
&item_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(item_handle_name.data(),
|
|
item_handle_name.size());
|
|
handle_section_bytes += item_handle_bytes;
|
|
command_size += item_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Unseal(
|
|
const std::string& response,
|
|
TPM2B_SENSITIVE_DATA* out_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Unseal;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_data_bytes;
|
|
rc = Parse_TPM2B_SENSITIVE_DATA(
|
|
&buffer,
|
|
out_data,
|
|
&out_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_SENSITIVE_DATA(
|
|
&out_data_bytes,
|
|
out_data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void UnsealErrorCallback(
|
|
const Tpm::UnsealResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_SENSITIVE_DATA());
|
|
}
|
|
|
|
void UnsealResponseParser(
|
|
const Tpm::UnsealResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(UnsealErrorCallback, callback);
|
|
TPM2B_SENSITIVE_DATA out_data;
|
|
TPM_RC rc = Tpm::ParseResponse_Unseal(
|
|
response,
|
|
&out_data,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_data);
|
|
}
|
|
|
|
void Tpm::Unseal(
|
|
const TPMI_DH_OBJECT& item_handle,
|
|
const std::string& item_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const UnsealResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(UnsealErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(UnsealResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Unseal(
|
|
item_handle,
|
|
item_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::UnsealSync(
|
|
const TPMI_DH_OBJECT& item_handle,
|
|
const std::string& item_handle_name,
|
|
TPM2B_SENSITIVE_DATA* out_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Unseal(
|
|
item_handle,
|
|
item_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Unseal(
|
|
response,
|
|
out_data,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ObjectChangeAuth(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ObjectChangeAuth;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string parent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
parent_handle,
|
|
&parent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
new_auth,
|
|
&new_auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = new_auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
new_auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
hash->Update(parent_handle_name.data(),
|
|
parent_handle_name.size());
|
|
handle_section_bytes += parent_handle_bytes;
|
|
command_size += parent_handle_bytes.size();
|
|
hash->Update(new_auth_bytes.data(),
|
|
new_auth_bytes.size());
|
|
parameter_section_bytes += new_auth_bytes;
|
|
command_size += new_auth_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ObjectChangeAuth(
|
|
const std::string& response,
|
|
TPM2B_PRIVATE* out_private,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ObjectChangeAuth;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_private_bytes;
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&buffer,
|
|
out_private,
|
|
&out_private_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_private_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_private_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&out_private_bytes,
|
|
out_private,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ObjectChangeAuthErrorCallback(
|
|
const Tpm::ObjectChangeAuthResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PRIVATE());
|
|
}
|
|
|
|
void ObjectChangeAuthResponseParser(
|
|
const Tpm::ObjectChangeAuthResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ObjectChangeAuthErrorCallback, callback);
|
|
TPM2B_PRIVATE out_private;
|
|
TPM_RC rc = Tpm::ParseResponse_ObjectChangeAuth(
|
|
response,
|
|
&out_private,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_private);
|
|
}
|
|
|
|
void Tpm::ObjectChangeAuth(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ObjectChangeAuthResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ObjectChangeAuthErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ObjectChangeAuthResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ObjectChangeAuth(
|
|
object_handle,
|
|
object_handle_name,
|
|
parent_handle,
|
|
parent_handle_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ObjectChangeAuthSync(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
TPM2B_PRIVATE* out_private,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ObjectChangeAuth(
|
|
object_handle,
|
|
object_handle_name,
|
|
parent_handle,
|
|
parent_handle_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ObjectChangeAuth(
|
|
response,
|
|
out_private,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Duplicate(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& new_parent_handle,
|
|
const std::string& new_parent_handle_name,
|
|
const TPM2B_DATA& encryption_key_in,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Duplicate;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_parent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
new_parent_handle,
|
|
&new_parent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string encryption_key_in_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
encryption_key_in,
|
|
&encryption_key_in_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string symmetric_alg_bytes;
|
|
rc = Serialize_TPMT_SYM_DEF_OBJECT(
|
|
symmetric_alg,
|
|
&symmetric_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = encryption_key_in_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
encryption_key_in_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
hash->Update(new_parent_handle_name.data(),
|
|
new_parent_handle_name.size());
|
|
handle_section_bytes += new_parent_handle_bytes;
|
|
command_size += new_parent_handle_bytes.size();
|
|
hash->Update(encryption_key_in_bytes.data(),
|
|
encryption_key_in_bytes.size());
|
|
parameter_section_bytes += encryption_key_in_bytes;
|
|
command_size += encryption_key_in_bytes.size();
|
|
hash->Update(symmetric_alg_bytes.data(),
|
|
symmetric_alg_bytes.size());
|
|
parameter_section_bytes += symmetric_alg_bytes;
|
|
command_size += symmetric_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Duplicate(
|
|
const std::string& response,
|
|
TPM2B_DATA* encryption_key_out,
|
|
TPM2B_PRIVATE* duplicate,
|
|
TPM2B_ENCRYPTED_SECRET* out_sym_seed,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Duplicate;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string encryption_key_out_bytes;
|
|
rc = Parse_TPM2B_DATA(
|
|
&buffer,
|
|
encryption_key_out,
|
|
&encryption_key_out_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string duplicate_bytes;
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&buffer,
|
|
duplicate,
|
|
&duplicate_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string out_sym_seed_bytes;
|
|
rc = Parse_TPM2B_ENCRYPTED_SECRET(
|
|
&buffer,
|
|
out_sym_seed,
|
|
&out_sym_seed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = encryption_key_out_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
encryption_key_out_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DATA(
|
|
&encryption_key_out_bytes,
|
|
encryption_key_out,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void DuplicateErrorCallback(
|
|
const Tpm::DuplicateResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DATA(),
|
|
TPM2B_PRIVATE(),
|
|
TPM2B_ENCRYPTED_SECRET());
|
|
}
|
|
|
|
void DuplicateResponseParser(
|
|
const Tpm::DuplicateResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DuplicateErrorCallback, callback);
|
|
TPM2B_DATA encryption_key_out;
|
|
TPM2B_PRIVATE duplicate;
|
|
TPM2B_ENCRYPTED_SECRET out_sym_seed;
|
|
TPM_RC rc = Tpm::ParseResponse_Duplicate(
|
|
response,
|
|
&encryption_key_out,
|
|
&duplicate,
|
|
&out_sym_seed,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
encryption_key_out,
|
|
duplicate,
|
|
out_sym_seed);
|
|
}
|
|
|
|
void Tpm::Duplicate(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& new_parent_handle,
|
|
const std::string& new_parent_handle_name,
|
|
const TPM2B_DATA& encryption_key_in,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const DuplicateResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DuplicateErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(DuplicateResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Duplicate(
|
|
object_handle,
|
|
object_handle_name,
|
|
new_parent_handle,
|
|
new_parent_handle_name,
|
|
encryption_key_in,
|
|
symmetric_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::DuplicateSync(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& new_parent_handle,
|
|
const std::string& new_parent_handle_name,
|
|
const TPM2B_DATA& encryption_key_in,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
TPM2B_DATA* encryption_key_out,
|
|
TPM2B_PRIVATE* duplicate,
|
|
TPM2B_ENCRYPTED_SECRET* out_sym_seed,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Duplicate(
|
|
object_handle,
|
|
object_handle_name,
|
|
new_parent_handle,
|
|
new_parent_handle_name,
|
|
encryption_key_in,
|
|
symmetric_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Duplicate(
|
|
response,
|
|
encryption_key_out,
|
|
duplicate,
|
|
out_sym_seed,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Rewrap(
|
|
const TPMI_DH_OBJECT& old_parent,
|
|
const std::string& old_parent_name,
|
|
const TPMI_DH_OBJECT& new_parent,
|
|
const std::string& new_parent_name,
|
|
const TPM2B_PRIVATE& in_duplicate,
|
|
const TPM2B_NAME& name,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Rewrap;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string old_parent_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
old_parent,
|
|
&old_parent_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_parent_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
new_parent,
|
|
&new_parent_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_duplicate_bytes;
|
|
rc = Serialize_TPM2B_PRIVATE(
|
|
in_duplicate,
|
|
&in_duplicate_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string name_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
name,
|
|
&name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_sym_seed_bytes;
|
|
rc = Serialize_TPM2B_ENCRYPTED_SECRET(
|
|
in_sym_seed,
|
|
&in_sym_seed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_duplicate_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_duplicate_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(old_parent_name.data(),
|
|
old_parent_name.size());
|
|
handle_section_bytes += old_parent_bytes;
|
|
command_size += old_parent_bytes.size();
|
|
hash->Update(new_parent_name.data(),
|
|
new_parent_name.size());
|
|
handle_section_bytes += new_parent_bytes;
|
|
command_size += new_parent_bytes.size();
|
|
hash->Update(in_duplicate_bytes.data(),
|
|
in_duplicate_bytes.size());
|
|
parameter_section_bytes += in_duplicate_bytes;
|
|
command_size += in_duplicate_bytes.size();
|
|
hash->Update(name_bytes.data(),
|
|
name_bytes.size());
|
|
parameter_section_bytes += name_bytes;
|
|
command_size += name_bytes.size();
|
|
hash->Update(in_sym_seed_bytes.data(),
|
|
in_sym_seed_bytes.size());
|
|
parameter_section_bytes += in_sym_seed_bytes;
|
|
command_size += in_sym_seed_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Rewrap(
|
|
const std::string& response,
|
|
TPM2B_PRIVATE* out_duplicate,
|
|
TPM2B_ENCRYPTED_SECRET* out_sym_seed,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Rewrap;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_duplicate_bytes;
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&buffer,
|
|
out_duplicate,
|
|
&out_duplicate_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string out_sym_seed_bytes;
|
|
rc = Parse_TPM2B_ENCRYPTED_SECRET(
|
|
&buffer,
|
|
out_sym_seed,
|
|
&out_sym_seed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_duplicate_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_duplicate_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&out_duplicate_bytes,
|
|
out_duplicate,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void RewrapErrorCallback(
|
|
const Tpm::RewrapResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PRIVATE(),
|
|
TPM2B_ENCRYPTED_SECRET());
|
|
}
|
|
|
|
void RewrapResponseParser(
|
|
const Tpm::RewrapResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RewrapErrorCallback, callback);
|
|
TPM2B_PRIVATE out_duplicate;
|
|
TPM2B_ENCRYPTED_SECRET out_sym_seed;
|
|
TPM_RC rc = Tpm::ParseResponse_Rewrap(
|
|
response,
|
|
&out_duplicate,
|
|
&out_sym_seed,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_duplicate,
|
|
out_sym_seed);
|
|
}
|
|
|
|
void Tpm::Rewrap(
|
|
const TPMI_DH_OBJECT& old_parent,
|
|
const std::string& old_parent_name,
|
|
const TPMI_DH_OBJECT& new_parent,
|
|
const std::string& new_parent_name,
|
|
const TPM2B_PRIVATE& in_duplicate,
|
|
const TPM2B_NAME& name,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const RewrapResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RewrapErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(RewrapResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Rewrap(
|
|
old_parent,
|
|
old_parent_name,
|
|
new_parent,
|
|
new_parent_name,
|
|
in_duplicate,
|
|
name,
|
|
in_sym_seed,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::RewrapSync(
|
|
const TPMI_DH_OBJECT& old_parent,
|
|
const std::string& old_parent_name,
|
|
const TPMI_DH_OBJECT& new_parent,
|
|
const std::string& new_parent_name,
|
|
const TPM2B_PRIVATE& in_duplicate,
|
|
const TPM2B_NAME& name,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
TPM2B_PRIVATE* out_duplicate,
|
|
TPM2B_ENCRYPTED_SECRET* out_sym_seed,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Rewrap(
|
|
old_parent,
|
|
old_parent_name,
|
|
new_parent,
|
|
new_parent_name,
|
|
in_duplicate,
|
|
name,
|
|
in_sym_seed,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Rewrap(
|
|
response,
|
|
out_duplicate,
|
|
out_sym_seed,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Import(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_DATA& encryption_key,
|
|
const TPM2B_PUBLIC& object_public,
|
|
const TPM2B_PRIVATE& duplicate,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Import;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string parent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
parent_handle,
|
|
&parent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string encryption_key_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
encryption_key,
|
|
&encryption_key_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_public_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC(
|
|
object_public,
|
|
&object_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string duplicate_bytes;
|
|
rc = Serialize_TPM2B_PRIVATE(
|
|
duplicate,
|
|
&duplicate_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_sym_seed_bytes;
|
|
rc = Serialize_TPM2B_ENCRYPTED_SECRET(
|
|
in_sym_seed,
|
|
&in_sym_seed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string symmetric_alg_bytes;
|
|
rc = Serialize_TPMT_SYM_DEF_OBJECT(
|
|
symmetric_alg,
|
|
&symmetric_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = encryption_key_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
encryption_key_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(parent_handle_name.data(),
|
|
parent_handle_name.size());
|
|
handle_section_bytes += parent_handle_bytes;
|
|
command_size += parent_handle_bytes.size();
|
|
hash->Update(encryption_key_bytes.data(),
|
|
encryption_key_bytes.size());
|
|
parameter_section_bytes += encryption_key_bytes;
|
|
command_size += encryption_key_bytes.size();
|
|
hash->Update(object_public_bytes.data(),
|
|
object_public_bytes.size());
|
|
parameter_section_bytes += object_public_bytes;
|
|
command_size += object_public_bytes.size();
|
|
hash->Update(duplicate_bytes.data(),
|
|
duplicate_bytes.size());
|
|
parameter_section_bytes += duplicate_bytes;
|
|
command_size += duplicate_bytes.size();
|
|
hash->Update(in_sym_seed_bytes.data(),
|
|
in_sym_seed_bytes.size());
|
|
parameter_section_bytes += in_sym_seed_bytes;
|
|
command_size += in_sym_seed_bytes.size();
|
|
hash->Update(symmetric_alg_bytes.data(),
|
|
symmetric_alg_bytes.size());
|
|
parameter_section_bytes += symmetric_alg_bytes;
|
|
command_size += symmetric_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Import(
|
|
const std::string& response,
|
|
TPM2B_PRIVATE* out_private,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Import;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_private_bytes;
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&buffer,
|
|
out_private,
|
|
&out_private_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_private_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_private_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PRIVATE(
|
|
&out_private_bytes,
|
|
out_private,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ImportErrorCallback(
|
|
const Tpm::ImportResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PRIVATE());
|
|
}
|
|
|
|
void ImportResponseParser(
|
|
const Tpm::ImportResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ImportErrorCallback, callback);
|
|
TPM2B_PRIVATE out_private;
|
|
TPM_RC rc = Tpm::ParseResponse_Import(
|
|
response,
|
|
&out_private,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_private);
|
|
}
|
|
|
|
void Tpm::Import(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_DATA& encryption_key,
|
|
const TPM2B_PUBLIC& object_public,
|
|
const TPM2B_PRIVATE& duplicate,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ImportResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ImportErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ImportResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Import(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
encryption_key,
|
|
object_public,
|
|
duplicate,
|
|
in_sym_seed,
|
|
symmetric_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ImportSync(
|
|
const TPMI_DH_OBJECT& parent_handle,
|
|
const std::string& parent_handle_name,
|
|
const TPM2B_DATA& encryption_key,
|
|
const TPM2B_PUBLIC& object_public,
|
|
const TPM2B_PRIVATE& duplicate,
|
|
const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
|
|
const TPMT_SYM_DEF_OBJECT& symmetric_alg,
|
|
TPM2B_PRIVATE* out_private,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Import(
|
|
parent_handle,
|
|
parent_handle_name,
|
|
encryption_key,
|
|
object_public,
|
|
duplicate,
|
|
in_sym_seed,
|
|
symmetric_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Import(
|
|
response,
|
|
out_private,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_RSA_Encrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& message,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_RSA_Encrypt;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string message_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC_KEY_RSA(
|
|
message,
|
|
&message_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_RSA_DECRYPT(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string label_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
label,
|
|
&label_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = message_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
message_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(message_bytes.data(),
|
|
message_bytes.size());
|
|
parameter_section_bytes += message_bytes;
|
|
command_size += message_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(label_bytes.data(),
|
|
label_bytes.size());
|
|
parameter_section_bytes += label_bytes;
|
|
command_size += label_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_RSA_Encrypt(
|
|
const std::string& response,
|
|
TPM2B_PUBLIC_KEY_RSA* out_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_RSA_Encrypt;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_data_bytes;
|
|
rc = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
&buffer,
|
|
out_data,
|
|
&out_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
&out_data_bytes,
|
|
out_data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void RSA_EncryptErrorCallback(
|
|
const Tpm::RSA_EncryptResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PUBLIC_KEY_RSA());
|
|
}
|
|
|
|
void RSA_EncryptResponseParser(
|
|
const Tpm::RSA_EncryptResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RSA_EncryptErrorCallback, callback);
|
|
TPM2B_PUBLIC_KEY_RSA out_data;
|
|
TPM_RC rc = Tpm::ParseResponse_RSA_Encrypt(
|
|
response,
|
|
&out_data,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_data);
|
|
}
|
|
|
|
void Tpm::RSA_Encrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& message,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const RSA_EncryptResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RSA_EncryptErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(RSA_EncryptResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_RSA_Encrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
message,
|
|
in_scheme,
|
|
label,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::RSA_EncryptSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& message,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
TPM2B_PUBLIC_KEY_RSA* out_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_RSA_Encrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
message,
|
|
in_scheme,
|
|
label,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_RSA_Encrypt(
|
|
response,
|
|
out_data,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_RSA_Decrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& cipher_text,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_RSA_Decrypt;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string cipher_text_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC_KEY_RSA(
|
|
cipher_text,
|
|
&cipher_text_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_RSA_DECRYPT(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string label_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
label,
|
|
&label_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = cipher_text_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
cipher_text_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(cipher_text_bytes.data(),
|
|
cipher_text_bytes.size());
|
|
parameter_section_bytes += cipher_text_bytes;
|
|
command_size += cipher_text_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(label_bytes.data(),
|
|
label_bytes.size());
|
|
parameter_section_bytes += label_bytes;
|
|
command_size += label_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_RSA_Decrypt(
|
|
const std::string& response,
|
|
TPM2B_PUBLIC_KEY_RSA* message,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_RSA_Decrypt;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string message_bytes;
|
|
rc = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
&buffer,
|
|
message,
|
|
&message_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = message_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
message_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PUBLIC_KEY_RSA(
|
|
&message_bytes,
|
|
message,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void RSA_DecryptErrorCallback(
|
|
const Tpm::RSA_DecryptResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_PUBLIC_KEY_RSA());
|
|
}
|
|
|
|
void RSA_DecryptResponseParser(
|
|
const Tpm::RSA_DecryptResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RSA_DecryptErrorCallback, callback);
|
|
TPM2B_PUBLIC_KEY_RSA message;
|
|
TPM_RC rc = Tpm::ParseResponse_RSA_Decrypt(
|
|
response,
|
|
&message,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
message);
|
|
}
|
|
|
|
void Tpm::RSA_Decrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& cipher_text,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const RSA_DecryptResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(RSA_DecryptErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(RSA_DecryptResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_RSA_Decrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
cipher_text,
|
|
in_scheme,
|
|
label,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::RSA_DecryptSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_PUBLIC_KEY_RSA& cipher_text,
|
|
const TPMT_RSA_DECRYPT& in_scheme,
|
|
const TPM2B_DATA& label,
|
|
TPM2B_PUBLIC_KEY_RSA* message,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_RSA_Decrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
cipher_text,
|
|
in_scheme,
|
|
label,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_RSA_Decrypt(
|
|
response,
|
|
message,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ECDH_KeyGen(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ECDH_KeyGen;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ECDH_KeyGen(
|
|
const std::string& response,
|
|
TPM2B_ECC_POINT* z_point,
|
|
TPM2B_ECC_POINT* pub_point,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ECDH_KeyGen;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string z_point_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
z_point,
|
|
&z_point_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pub_point_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
pub_point,
|
|
&pub_point_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = z_point_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
z_point_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&z_point_bytes,
|
|
z_point,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ECDH_KeyGenErrorCallback(
|
|
const Tpm::ECDH_KeyGenResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ECC_POINT(),
|
|
TPM2B_ECC_POINT());
|
|
}
|
|
|
|
void ECDH_KeyGenResponseParser(
|
|
const Tpm::ECDH_KeyGenResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECDH_KeyGenErrorCallback, callback);
|
|
TPM2B_ECC_POINT z_point;
|
|
TPM2B_ECC_POINT pub_point;
|
|
TPM_RC rc = Tpm::ParseResponse_ECDH_KeyGen(
|
|
response,
|
|
&z_point,
|
|
&pub_point,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
z_point,
|
|
pub_point);
|
|
}
|
|
|
|
void Tpm::ECDH_KeyGen(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ECDH_KeyGenResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECDH_KeyGenErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ECDH_KeyGenResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECDH_KeyGen(
|
|
key_handle,
|
|
key_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ECDH_KeyGenSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
TPM2B_ECC_POINT* z_point,
|
|
TPM2B_ECC_POINT* pub_point,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECDH_KeyGen(
|
|
key_handle,
|
|
key_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ECDH_KeyGen(
|
|
response,
|
|
z_point,
|
|
pub_point,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ECDH_ZGen(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ECC_POINT& in_point,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ECDH_ZGen;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_point_bytes;
|
|
rc = Serialize_TPM2B_ECC_POINT(
|
|
in_point,
|
|
&in_point_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_point_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_point_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(in_point_bytes.data(),
|
|
in_point_bytes.size());
|
|
parameter_section_bytes += in_point_bytes;
|
|
command_size += in_point_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ECDH_ZGen(
|
|
const std::string& response,
|
|
TPM2B_ECC_POINT* out_point,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ECDH_ZGen;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_point_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
out_point,
|
|
&out_point_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_point_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_point_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&out_point_bytes,
|
|
out_point,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ECDH_ZGenErrorCallback(
|
|
const Tpm::ECDH_ZGenResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ECC_POINT());
|
|
}
|
|
|
|
void ECDH_ZGenResponseParser(
|
|
const Tpm::ECDH_ZGenResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECDH_ZGenErrorCallback, callback);
|
|
TPM2B_ECC_POINT out_point;
|
|
TPM_RC rc = Tpm::ParseResponse_ECDH_ZGen(
|
|
response,
|
|
&out_point,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_point);
|
|
}
|
|
|
|
void Tpm::ECDH_ZGen(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ECC_POINT& in_point,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ECDH_ZGenResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECDH_ZGenErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ECDH_ZGenResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECDH_ZGen(
|
|
key_handle,
|
|
key_handle_name,
|
|
in_point,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ECDH_ZGenSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_ECC_POINT& in_point,
|
|
TPM2B_ECC_POINT* out_point,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECDH_ZGen(
|
|
key_handle,
|
|
key_handle_name,
|
|
in_point,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ECDH_ZGen(
|
|
response,
|
|
out_point,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ECC_Parameters(
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ECC_Parameters;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string curve_id_bytes;
|
|
rc = Serialize_TPMI_ECC_CURVE(
|
|
curve_id,
|
|
&curve_id_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(curve_id_bytes.data(),
|
|
curve_id_bytes.size());
|
|
parameter_section_bytes += curve_id_bytes;
|
|
command_size += curve_id_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ECC_Parameters(
|
|
const std::string& response,
|
|
TPMS_ALGORITHM_DETAIL_ECC* parameters,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ECC_Parameters;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string parameters_bytes;
|
|
rc = Parse_TPMS_ALGORITHM_DETAIL_ECC(
|
|
&buffer,
|
|
parameters,
|
|
¶meters_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ECC_ParametersErrorCallback(
|
|
const Tpm::ECC_ParametersResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMS_ALGORITHM_DETAIL_ECC());
|
|
}
|
|
|
|
void ECC_ParametersResponseParser(
|
|
const Tpm::ECC_ParametersResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECC_ParametersErrorCallback, callback);
|
|
TPMS_ALGORITHM_DETAIL_ECC parameters;
|
|
TPM_RC rc = Tpm::ParseResponse_ECC_Parameters(
|
|
response,
|
|
¶meters,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
parameters);
|
|
}
|
|
|
|
void Tpm::ECC_Parameters(
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ECC_ParametersResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ECC_ParametersErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ECC_ParametersResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECC_Parameters(
|
|
curve_id,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ECC_ParametersSync(
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
TPMS_ALGORITHM_DETAIL_ECC* parameters,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ECC_Parameters(
|
|
curve_id,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ECC_Parameters(
|
|
response,
|
|
parameters,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ZGen_2Phase(
|
|
const TPMI_DH_OBJECT& key_a,
|
|
const std::string& key_a_name,
|
|
const TPM2B_ECC_POINT& in_qs_b,
|
|
const TPM2B_ECC_POINT& in_qe_b,
|
|
const TPMI_ECC_KEY_EXCHANGE& in_scheme,
|
|
const UINT16& counter,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ZGen_2Phase;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_a_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_a,
|
|
&key_a_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_qs_b_bytes;
|
|
rc = Serialize_TPM2B_ECC_POINT(
|
|
in_qs_b,
|
|
&in_qs_b_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_qe_b_bytes;
|
|
rc = Serialize_TPM2B_ECC_POINT(
|
|
in_qe_b,
|
|
&in_qe_b_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMI_ECC_KEY_EXCHANGE(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string counter_bytes;
|
|
rc = Serialize_UINT16(
|
|
counter,
|
|
&counter_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_qs_b_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_qs_b_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_a_name.data(),
|
|
key_a_name.size());
|
|
handle_section_bytes += key_a_bytes;
|
|
command_size += key_a_bytes.size();
|
|
hash->Update(in_qs_b_bytes.data(),
|
|
in_qs_b_bytes.size());
|
|
parameter_section_bytes += in_qs_b_bytes;
|
|
command_size += in_qs_b_bytes.size();
|
|
hash->Update(in_qe_b_bytes.data(),
|
|
in_qe_b_bytes.size());
|
|
parameter_section_bytes += in_qe_b_bytes;
|
|
command_size += in_qe_b_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(counter_bytes.data(),
|
|
counter_bytes.size());
|
|
parameter_section_bytes += counter_bytes;
|
|
command_size += counter_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ZGen_2Phase(
|
|
const std::string& response,
|
|
TPM2B_ECC_POINT* out_z1,
|
|
TPM2B_ECC_POINT* out_z2,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ZGen_2Phase;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_z1_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
out_z1,
|
|
&out_z1_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string out_z2_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
out_z2,
|
|
&out_z2_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_z1_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_z1_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&out_z1_bytes,
|
|
out_z1,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ZGen_2PhaseErrorCallback(
|
|
const Tpm::ZGen_2PhaseResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ECC_POINT(),
|
|
TPM2B_ECC_POINT());
|
|
}
|
|
|
|
void ZGen_2PhaseResponseParser(
|
|
const Tpm::ZGen_2PhaseResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ZGen_2PhaseErrorCallback, callback);
|
|
TPM2B_ECC_POINT out_z1;
|
|
TPM2B_ECC_POINT out_z2;
|
|
TPM_RC rc = Tpm::ParseResponse_ZGen_2Phase(
|
|
response,
|
|
&out_z1,
|
|
&out_z2,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_z1,
|
|
out_z2);
|
|
}
|
|
|
|
void Tpm::ZGen_2Phase(
|
|
const TPMI_DH_OBJECT& key_a,
|
|
const std::string& key_a_name,
|
|
const TPM2B_ECC_POINT& in_qs_b,
|
|
const TPM2B_ECC_POINT& in_qe_b,
|
|
const TPMI_ECC_KEY_EXCHANGE& in_scheme,
|
|
const UINT16& counter,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ZGen_2PhaseResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ZGen_2PhaseErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ZGen_2PhaseResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ZGen_2Phase(
|
|
key_a,
|
|
key_a_name,
|
|
in_qs_b,
|
|
in_qe_b,
|
|
in_scheme,
|
|
counter,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ZGen_2PhaseSync(
|
|
const TPMI_DH_OBJECT& key_a,
|
|
const std::string& key_a_name,
|
|
const TPM2B_ECC_POINT& in_qs_b,
|
|
const TPM2B_ECC_POINT& in_qe_b,
|
|
const TPMI_ECC_KEY_EXCHANGE& in_scheme,
|
|
const UINT16& counter,
|
|
TPM2B_ECC_POINT* out_z1,
|
|
TPM2B_ECC_POINT* out_z2,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ZGen_2Phase(
|
|
key_a,
|
|
key_a_name,
|
|
in_qs_b,
|
|
in_qe_b,
|
|
in_scheme,
|
|
counter,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ZGen_2Phase(
|
|
response,
|
|
out_z1,
|
|
out_z2,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_EncryptDecrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPMI_YES_NO& decrypt,
|
|
const TPMI_ALG_SYM_MODE& mode,
|
|
const TPM2B_IV& iv_in,
|
|
const TPM2B_MAX_BUFFER& in_data,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_EncryptDecrypt;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string decrypt_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
decrypt,
|
|
&decrypt_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string mode_bytes;
|
|
rc = Serialize_TPMI_ALG_SYM_MODE(
|
|
mode,
|
|
&mode_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string iv_in_bytes;
|
|
rc = Serialize_TPM2B_IV(
|
|
iv_in,
|
|
&iv_in_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_data_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
in_data,
|
|
&in_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(decrypt_bytes.data(),
|
|
decrypt_bytes.size());
|
|
parameter_section_bytes += decrypt_bytes;
|
|
command_size += decrypt_bytes.size();
|
|
hash->Update(mode_bytes.data(),
|
|
mode_bytes.size());
|
|
parameter_section_bytes += mode_bytes;
|
|
command_size += mode_bytes.size();
|
|
hash->Update(iv_in_bytes.data(),
|
|
iv_in_bytes.size());
|
|
parameter_section_bytes += iv_in_bytes;
|
|
command_size += iv_in_bytes.size();
|
|
hash->Update(in_data_bytes.data(),
|
|
in_data_bytes.size());
|
|
parameter_section_bytes += in_data_bytes;
|
|
command_size += in_data_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_EncryptDecrypt(
|
|
const std::string& response,
|
|
TPM2B_MAX_BUFFER* out_data,
|
|
TPM2B_IV* iv_out,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_EncryptDecrypt;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_data_bytes;
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&buffer,
|
|
out_data,
|
|
&out_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string iv_out_bytes;
|
|
rc = Parse_TPM2B_IV(
|
|
&buffer,
|
|
iv_out,
|
|
&iv_out_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&out_data_bytes,
|
|
out_data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void EncryptDecryptErrorCallback(
|
|
const Tpm::EncryptDecryptResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_MAX_BUFFER(),
|
|
TPM2B_IV());
|
|
}
|
|
|
|
void EncryptDecryptResponseParser(
|
|
const Tpm::EncryptDecryptResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EncryptDecryptErrorCallback, callback);
|
|
TPM2B_MAX_BUFFER out_data;
|
|
TPM2B_IV iv_out;
|
|
TPM_RC rc = Tpm::ParseResponse_EncryptDecrypt(
|
|
response,
|
|
&out_data,
|
|
&iv_out,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_data,
|
|
iv_out);
|
|
}
|
|
|
|
void Tpm::EncryptDecrypt(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPMI_YES_NO& decrypt,
|
|
const TPMI_ALG_SYM_MODE& mode,
|
|
const TPM2B_IV& iv_in,
|
|
const TPM2B_MAX_BUFFER& in_data,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const EncryptDecryptResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EncryptDecryptErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(EncryptDecryptResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EncryptDecrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
decrypt,
|
|
mode,
|
|
iv_in,
|
|
in_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::EncryptDecryptSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPMI_YES_NO& decrypt,
|
|
const TPMI_ALG_SYM_MODE& mode,
|
|
const TPM2B_IV& iv_in,
|
|
const TPM2B_MAX_BUFFER& in_data,
|
|
TPM2B_MAX_BUFFER* out_data,
|
|
TPM2B_IV* iv_out,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EncryptDecrypt(
|
|
key_handle,
|
|
key_handle_name,
|
|
decrypt,
|
|
mode,
|
|
iv_in,
|
|
in_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_EncryptDecrypt(
|
|
response,
|
|
out_data,
|
|
iv_out,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Hash(
|
|
const TPM2B_MAX_BUFFER& data,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Hash;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string data_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
data,
|
|
&data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hash_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
hash_alg,
|
|
&hash_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hierarchy_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
hierarchy,
|
|
&hierarchy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(data_bytes.data(),
|
|
data_bytes.size());
|
|
parameter_section_bytes += data_bytes;
|
|
command_size += data_bytes.size();
|
|
hash->Update(hash_alg_bytes.data(),
|
|
hash_alg_bytes.size());
|
|
parameter_section_bytes += hash_alg_bytes;
|
|
command_size += hash_alg_bytes.size();
|
|
hash->Update(hierarchy_bytes.data(),
|
|
hierarchy_bytes.size());
|
|
parameter_section_bytes += hierarchy_bytes;
|
|
command_size += hierarchy_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Hash(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* out_hash,
|
|
TPMT_TK_HASHCHECK* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Hash;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_hash_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
out_hash,
|
|
&out_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string validation_bytes;
|
|
rc = Parse_TPMT_TK_HASHCHECK(
|
|
&buffer,
|
|
validation,
|
|
&validation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_hash_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_hash_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&out_hash_bytes,
|
|
out_hash,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HashErrorCallback(
|
|
const Tpm::HashResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST(),
|
|
TPMT_TK_HASHCHECK());
|
|
}
|
|
|
|
void HashResponseParser(
|
|
const Tpm::HashResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HashErrorCallback, callback);
|
|
TPM2B_DIGEST out_hash;
|
|
TPMT_TK_HASHCHECK validation;
|
|
TPM_RC rc = Tpm::ParseResponse_Hash(
|
|
response,
|
|
&out_hash,
|
|
&validation,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_hash,
|
|
validation);
|
|
}
|
|
|
|
void Tpm::Hash(
|
|
const TPM2B_MAX_BUFFER& data,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HashResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HashErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HashResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Hash(
|
|
data,
|
|
hash_alg,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HashSync(
|
|
const TPM2B_MAX_BUFFER& data,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
TPM2B_DIGEST* out_hash,
|
|
TPMT_TK_HASHCHECK* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Hash(
|
|
data,
|
|
hash_alg,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Hash(
|
|
response,
|
|
out_hash,
|
|
validation,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_HMAC(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_HMAC;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
handle,
|
|
&handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string buffer_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
buffer,
|
|
&buffer_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hash_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
hash_alg,
|
|
&hash_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = buffer_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
buffer_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(handle_name.data(),
|
|
handle_name.size());
|
|
handle_section_bytes += handle_bytes;
|
|
command_size += handle_bytes.size();
|
|
hash->Update(buffer_bytes.data(),
|
|
buffer_bytes.size());
|
|
parameter_section_bytes += buffer_bytes;
|
|
command_size += buffer_bytes.size();
|
|
hash->Update(hash_alg_bytes.data(),
|
|
hash_alg_bytes.size());
|
|
parameter_section_bytes += hash_alg_bytes;
|
|
command_size += hash_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_HMAC(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* out_hmac,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_HMAC;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_hmac_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
out_hmac,
|
|
&out_hmac_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_hmac_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_hmac_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&out_hmac_bytes,
|
|
out_hmac,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HMACErrorCallback(
|
|
const Tpm::HMACResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST());
|
|
}
|
|
|
|
void HMACResponseParser(
|
|
const Tpm::HMACResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HMACErrorCallback, callback);
|
|
TPM2B_DIGEST out_hmac;
|
|
TPM_RC rc = Tpm::ParseResponse_HMAC(
|
|
response,
|
|
&out_hmac,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
out_hmac);
|
|
}
|
|
|
|
void Tpm::HMAC(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HMACResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HMACErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HMACResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HMAC(
|
|
handle,
|
|
handle_name,
|
|
buffer,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HMACSync(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
TPM2B_DIGEST* out_hmac,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HMAC(
|
|
handle,
|
|
handle_name,
|
|
buffer,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_HMAC(
|
|
response,
|
|
out_hmac,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetRandom(
|
|
const UINT16& bytes_requested,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetRandom;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string bytes_requested_bytes;
|
|
rc = Serialize_UINT16(
|
|
bytes_requested,
|
|
&bytes_requested_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(bytes_requested_bytes.data(),
|
|
bytes_requested_bytes.size());
|
|
parameter_section_bytes += bytes_requested_bytes;
|
|
command_size += bytes_requested_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetRandom(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* random_bytes,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetRandom;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string random_bytes_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
random_bytes,
|
|
&random_bytes_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = random_bytes_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
random_bytes_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&random_bytes_bytes,
|
|
random_bytes,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetRandomErrorCallback(
|
|
const Tpm::GetRandomResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST());
|
|
}
|
|
|
|
void GetRandomResponseParser(
|
|
const Tpm::GetRandomResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetRandomErrorCallback, callback);
|
|
TPM2B_DIGEST random_bytes;
|
|
TPM_RC rc = Tpm::ParseResponse_GetRandom(
|
|
response,
|
|
&random_bytes,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
random_bytes);
|
|
}
|
|
|
|
void Tpm::GetRandom(
|
|
const UINT16& bytes_requested,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetRandomResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetRandomErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetRandomResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetRandom(
|
|
bytes_requested,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetRandomSync(
|
|
const UINT16& bytes_requested,
|
|
TPM2B_DIGEST* random_bytes,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetRandom(
|
|
bytes_requested,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetRandom(
|
|
response,
|
|
random_bytes,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_StirRandom(
|
|
const TPM2B_SENSITIVE_DATA& in_data,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_StirRandom;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_data_bytes;
|
|
rc = Serialize_TPM2B_SENSITIVE_DATA(
|
|
in_data,
|
|
&in_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(in_data_bytes.data(),
|
|
in_data_bytes.size());
|
|
parameter_section_bytes += in_data_bytes;
|
|
command_size += in_data_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_StirRandom(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_StirRandom;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void StirRandomErrorCallback(
|
|
const Tpm::StirRandomResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void StirRandomResponseParser(
|
|
const Tpm::StirRandomResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StirRandomErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_StirRandom(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::StirRandom(
|
|
const TPM2B_SENSITIVE_DATA& in_data,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const StirRandomResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(StirRandomErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(StirRandomResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_StirRandom(
|
|
in_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::StirRandomSync(
|
|
const TPM2B_SENSITIVE_DATA& in_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_StirRandom(
|
|
in_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_StirRandom(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_HMAC_Start(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_HMAC_Start;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
handle,
|
|
&handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hash_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
hash_alg,
|
|
&hash_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(handle_name.data(),
|
|
handle_name.size());
|
|
handle_section_bytes += handle_bytes;
|
|
command_size += handle_bytes.size();
|
|
hash->Update(auth_bytes.data(),
|
|
auth_bytes.size());
|
|
parameter_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(hash_alg_bytes.data(),
|
|
hash_alg_bytes.size());
|
|
parameter_section_bytes += hash_alg_bytes;
|
|
command_size += hash_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_HMAC_Start(
|
|
const std::string& response,
|
|
TPMI_DH_OBJECT* sequence_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string sequence_handle_bytes;
|
|
rc = Parse_TPMI_DH_OBJECT(
|
|
&buffer,
|
|
sequence_handle,
|
|
&sequence_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_HMAC_Start;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HMAC_StartErrorCallback(
|
|
const Tpm::HMAC_StartResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_DH_OBJECT());
|
|
}
|
|
|
|
void HMAC_StartResponseParser(
|
|
const Tpm::HMAC_StartResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HMAC_StartErrorCallback, callback);
|
|
TPMI_DH_OBJECT sequence_handle;
|
|
TPM_RC rc = Tpm::ParseResponse_HMAC_Start(
|
|
response,
|
|
&sequence_handle,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
sequence_handle);
|
|
}
|
|
|
|
void Tpm::HMAC_Start(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HMAC_StartResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HMAC_StartErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HMAC_StartResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HMAC_Start(
|
|
handle,
|
|
handle_name,
|
|
auth,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HMAC_StartSync(
|
|
const TPMI_DH_OBJECT& handle,
|
|
const std::string& handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
TPMI_DH_OBJECT* sequence_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HMAC_Start(
|
|
handle,
|
|
handle_name,
|
|
auth,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_HMAC_Start(
|
|
response,
|
|
sequence_handle,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_HashSequenceStart(
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_HashSequenceStart;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hash_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
hash_alg,
|
|
&hash_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_bytes.data(),
|
|
auth_bytes.size());
|
|
parameter_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(hash_alg_bytes.data(),
|
|
hash_alg_bytes.size());
|
|
parameter_section_bytes += hash_alg_bytes;
|
|
command_size += hash_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_HashSequenceStart(
|
|
const std::string& response,
|
|
TPMI_DH_OBJECT* sequence_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string sequence_handle_bytes;
|
|
rc = Parse_TPMI_DH_OBJECT(
|
|
&buffer,
|
|
sequence_handle,
|
|
&sequence_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_HashSequenceStart;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HashSequenceStartErrorCallback(
|
|
const Tpm::HashSequenceStartResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_DH_OBJECT());
|
|
}
|
|
|
|
void HashSequenceStartResponseParser(
|
|
const Tpm::HashSequenceStartResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HashSequenceStartErrorCallback, callback);
|
|
TPMI_DH_OBJECT sequence_handle;
|
|
TPM_RC rc = Tpm::ParseResponse_HashSequenceStart(
|
|
response,
|
|
&sequence_handle,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
sequence_handle);
|
|
}
|
|
|
|
void Tpm::HashSequenceStart(
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HashSequenceStartResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HashSequenceStartErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HashSequenceStartResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HashSequenceStart(
|
|
auth,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HashSequenceStartSync(
|
|
const TPM2B_AUTH& auth,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
TPMI_DH_OBJECT* sequence_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HashSequenceStart(
|
|
auth,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_HashSequenceStart(
|
|
response,
|
|
sequence_handle,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SequenceUpdate(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SequenceUpdate;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sequence_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sequence_handle,
|
|
&sequence_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string buffer_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
buffer,
|
|
&buffer_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = buffer_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
buffer_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sequence_handle_name.data(),
|
|
sequence_handle_name.size());
|
|
handle_section_bytes += sequence_handle_bytes;
|
|
command_size += sequence_handle_bytes.size();
|
|
hash->Update(buffer_bytes.data(),
|
|
buffer_bytes.size());
|
|
parameter_section_bytes += buffer_bytes;
|
|
command_size += buffer_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SequenceUpdate(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SequenceUpdate;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SequenceUpdateErrorCallback(
|
|
const Tpm::SequenceUpdateResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void SequenceUpdateResponseParser(
|
|
const Tpm::SequenceUpdateResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SequenceUpdateErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_SequenceUpdate(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::SequenceUpdate(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SequenceUpdateResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SequenceUpdateErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SequenceUpdateResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SequenceUpdate(
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SequenceUpdateSync(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SequenceUpdate(
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SequenceUpdate(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SequenceComplete(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SequenceComplete;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sequence_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sequence_handle,
|
|
&sequence_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string buffer_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
buffer,
|
|
&buffer_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hierarchy_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
hierarchy,
|
|
&hierarchy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = buffer_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
buffer_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sequence_handle_name.data(),
|
|
sequence_handle_name.size());
|
|
handle_section_bytes += sequence_handle_bytes;
|
|
command_size += sequence_handle_bytes.size();
|
|
hash->Update(buffer_bytes.data(),
|
|
buffer_bytes.size());
|
|
parameter_section_bytes += buffer_bytes;
|
|
command_size += buffer_bytes.size();
|
|
hash->Update(hierarchy_bytes.data(),
|
|
hierarchy_bytes.size());
|
|
parameter_section_bytes += hierarchy_bytes;
|
|
command_size += hierarchy_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SequenceComplete(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* result,
|
|
TPMT_TK_HASHCHECK* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SequenceComplete;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string result_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
result,
|
|
&result_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string validation_bytes;
|
|
rc = Parse_TPMT_TK_HASHCHECK(
|
|
&buffer,
|
|
validation,
|
|
&validation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = result_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
result_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&result_bytes,
|
|
result,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SequenceCompleteErrorCallback(
|
|
const Tpm::SequenceCompleteResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST(),
|
|
TPMT_TK_HASHCHECK());
|
|
}
|
|
|
|
void SequenceCompleteResponseParser(
|
|
const Tpm::SequenceCompleteResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SequenceCompleteErrorCallback, callback);
|
|
TPM2B_DIGEST result;
|
|
TPMT_TK_HASHCHECK validation;
|
|
TPM_RC rc = Tpm::ParseResponse_SequenceComplete(
|
|
response,
|
|
&result,
|
|
&validation,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
result,
|
|
validation);
|
|
}
|
|
|
|
void Tpm::SequenceComplete(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SequenceCompleteResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SequenceCompleteErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SequenceCompleteResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SequenceComplete(
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SequenceCompleteSync(
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
const TPMI_RH_HIERARCHY& hierarchy,
|
|
TPM2B_DIGEST* result,
|
|
TPMT_TK_HASHCHECK* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SequenceComplete(
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
hierarchy,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SequenceComplete(
|
|
response,
|
|
result,
|
|
validation,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_EventSequenceComplete(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_EventSequenceComplete;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_handle,
|
|
&pcr_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sequence_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sequence_handle,
|
|
&sequence_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string buffer_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
buffer,
|
|
&buffer_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = buffer_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
buffer_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_handle_name.data(),
|
|
pcr_handle_name.size());
|
|
handle_section_bytes += pcr_handle_bytes;
|
|
command_size += pcr_handle_bytes.size();
|
|
hash->Update(sequence_handle_name.data(),
|
|
sequence_handle_name.size());
|
|
handle_section_bytes += sequence_handle_bytes;
|
|
command_size += sequence_handle_bytes.size();
|
|
hash->Update(buffer_bytes.data(),
|
|
buffer_bytes.size());
|
|
parameter_section_bytes += buffer_bytes;
|
|
command_size += buffer_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_EventSequenceComplete(
|
|
const std::string& response,
|
|
TPML_DIGEST_VALUES* results,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_EventSequenceComplete;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string results_bytes;
|
|
rc = Parse_TPML_DIGEST_VALUES(
|
|
&buffer,
|
|
results,
|
|
&results_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void EventSequenceCompleteErrorCallback(
|
|
const Tpm::EventSequenceCompleteResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPML_DIGEST_VALUES());
|
|
}
|
|
|
|
void EventSequenceCompleteResponseParser(
|
|
const Tpm::EventSequenceCompleteResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EventSequenceCompleteErrorCallback, callback);
|
|
TPML_DIGEST_VALUES results;
|
|
TPM_RC rc = Tpm::ParseResponse_EventSequenceComplete(
|
|
response,
|
|
&results,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
results);
|
|
}
|
|
|
|
void Tpm::EventSequenceComplete(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const EventSequenceCompleteResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EventSequenceCompleteErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(EventSequenceCompleteResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EventSequenceComplete(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::EventSequenceCompleteSync(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPMI_DH_OBJECT& sequence_handle,
|
|
const std::string& sequence_handle_name,
|
|
const TPM2B_MAX_BUFFER& buffer,
|
|
TPML_DIGEST_VALUES* results,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EventSequenceComplete(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
sequence_handle,
|
|
sequence_handle_name,
|
|
buffer,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_EventSequenceComplete(
|
|
response,
|
|
results,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Certify(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Certify;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Certify(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Certify;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string certify_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
certify_info,
|
|
&certify_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = certify_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
certify_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&certify_info_bytes,
|
|
certify_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void CertifyErrorCallback(
|
|
const Tpm::CertifyResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void CertifyResponseParser(
|
|
const Tpm::CertifyResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CertifyErrorCallback, callback);
|
|
TPM2B_ATTEST certify_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_Certify(
|
|
response,
|
|
&certify_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
certify_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::Certify(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const CertifyResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CertifyErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(CertifyResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Certify(
|
|
object_handle,
|
|
object_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::CertifySync(
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Certify(
|
|
object_handle,
|
|
object_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Certify(
|
|
response,
|
|
certify_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_CertifyCreation(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPM2B_DIGEST& creation_hash,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_CREATION& creation_ticket,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_CertifyCreation;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_hash_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
creation_hash,
|
|
&creation_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_ticket_bytes;
|
|
rc = Serialize_TPMT_TK_CREATION(
|
|
creation_ticket,
|
|
&creation_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(creation_hash_bytes.data(),
|
|
creation_hash_bytes.size());
|
|
parameter_section_bytes += creation_hash_bytes;
|
|
command_size += creation_hash_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(creation_ticket_bytes.data(),
|
|
creation_ticket_bytes.size());
|
|
parameter_section_bytes += creation_ticket_bytes;
|
|
command_size += creation_ticket_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_CertifyCreation(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_CertifyCreation;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string certify_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
certify_info,
|
|
&certify_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = certify_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
certify_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&certify_info_bytes,
|
|
certify_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void CertifyCreationErrorCallback(
|
|
const Tpm::CertifyCreationResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void CertifyCreationResponseParser(
|
|
const Tpm::CertifyCreationResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CertifyCreationErrorCallback, callback);
|
|
TPM2B_ATTEST certify_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_CertifyCreation(
|
|
response,
|
|
&certify_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
certify_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::CertifyCreation(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPM2B_DIGEST& creation_hash,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_CREATION& creation_ticket,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const CertifyCreationResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CertifyCreationErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(CertifyCreationResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_CertifyCreation(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
object_handle,
|
|
object_handle_name,
|
|
qualifying_data,
|
|
creation_hash,
|
|
in_scheme,
|
|
creation_ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::CertifyCreationSync(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPM2B_DIGEST& creation_hash,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_CREATION& creation_ticket,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_CertifyCreation(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
object_handle,
|
|
object_handle_name,
|
|
qualifying_data,
|
|
creation_hash,
|
|
in_scheme,
|
|
creation_ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_CertifyCreation(
|
|
response,
|
|
certify_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Quote(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPML_PCR_SELECTION& pcrselect,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Quote;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcrselect_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
pcrselect,
|
|
&pcrselect_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(pcrselect_bytes.data(),
|
|
pcrselect_bytes.size());
|
|
parameter_section_bytes += pcrselect_bytes;
|
|
command_size += pcrselect_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Quote(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* quoted,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Quote;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string quoted_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
quoted,
|
|
"ed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = quoted_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
quoted_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
"ed_bytes,
|
|
quoted,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void QuoteErrorCallback(
|
|
const Tpm::QuoteResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void QuoteResponseParser(
|
|
const Tpm::QuoteResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(QuoteErrorCallback, callback);
|
|
TPM2B_ATTEST quoted;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_Quote(
|
|
response,
|
|
"ed,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
quoted,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::Quote(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPML_PCR_SELECTION& pcrselect,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const QuoteResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(QuoteErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(QuoteResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Quote(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
pcrselect,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::QuoteSync(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPML_PCR_SELECTION& pcrselect,
|
|
TPM2B_ATTEST* quoted,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Quote(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
pcrselect,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Quote(
|
|
response,
|
|
quoted,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetSessionAuditDigest(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_SH_HMAC& session_handle,
|
|
const std::string& session_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetSessionAuditDigest;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string privacy_admin_handle_bytes;
|
|
rc = Serialize_TPMI_RH_ENDORSEMENT(
|
|
privacy_admin_handle,
|
|
&privacy_admin_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string session_handle_bytes;
|
|
rc = Serialize_TPMI_SH_HMAC(
|
|
session_handle,
|
|
&session_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(privacy_admin_handle_name.data(),
|
|
privacy_admin_handle_name.size());
|
|
handle_section_bytes += privacy_admin_handle_bytes;
|
|
command_size += privacy_admin_handle_bytes.size();
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(session_handle_name.data(),
|
|
session_handle_name.size());
|
|
handle_section_bytes += session_handle_bytes;
|
|
command_size += session_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetSessionAuditDigest(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* audit_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetSessionAuditDigest;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string audit_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
audit_info,
|
|
&audit_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = audit_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
audit_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&audit_info_bytes,
|
|
audit_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetSessionAuditDigestErrorCallback(
|
|
const Tpm::GetSessionAuditDigestResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void GetSessionAuditDigestResponseParser(
|
|
const Tpm::GetSessionAuditDigestResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetSessionAuditDigestErrorCallback, callback);
|
|
TPM2B_ATTEST audit_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_GetSessionAuditDigest(
|
|
response,
|
|
&audit_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
audit_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::GetSessionAuditDigest(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_SH_HMAC& session_handle,
|
|
const std::string& session_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetSessionAuditDigestResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetSessionAuditDigestErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetSessionAuditDigestResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetSessionAuditDigest(
|
|
privacy_admin_handle,
|
|
privacy_admin_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
session_handle,
|
|
session_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetSessionAuditDigestSync(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_SH_HMAC& session_handle,
|
|
const std::string& session_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
TPM2B_ATTEST* audit_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetSessionAuditDigest(
|
|
privacy_admin_handle,
|
|
privacy_admin_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
session_handle,
|
|
session_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetSessionAuditDigest(
|
|
response,
|
|
audit_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetCommandAuditDigest(
|
|
const TPMI_RH_ENDORSEMENT& privacy_handle,
|
|
const std::string& privacy_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetCommandAuditDigest;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string privacy_handle_bytes;
|
|
rc = Serialize_TPMI_RH_ENDORSEMENT(
|
|
privacy_handle,
|
|
&privacy_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(privacy_handle_name.data(),
|
|
privacy_handle_name.size());
|
|
handle_section_bytes += privacy_handle_bytes;
|
|
command_size += privacy_handle_bytes.size();
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetCommandAuditDigest(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* audit_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetCommandAuditDigest;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string audit_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
audit_info,
|
|
&audit_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = audit_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
audit_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&audit_info_bytes,
|
|
audit_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetCommandAuditDigestErrorCallback(
|
|
const Tpm::GetCommandAuditDigestResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void GetCommandAuditDigestResponseParser(
|
|
const Tpm::GetCommandAuditDigestResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetCommandAuditDigestErrorCallback, callback);
|
|
TPM2B_ATTEST audit_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_GetCommandAuditDigest(
|
|
response,
|
|
&audit_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
audit_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::GetCommandAuditDigest(
|
|
const TPMI_RH_ENDORSEMENT& privacy_handle,
|
|
const std::string& privacy_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetCommandAuditDigestResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetCommandAuditDigestErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetCommandAuditDigestResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetCommandAuditDigest(
|
|
privacy_handle,
|
|
privacy_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetCommandAuditDigestSync(
|
|
const TPMI_RH_ENDORSEMENT& privacy_handle,
|
|
const std::string& privacy_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
TPM2B_ATTEST* audit_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetCommandAuditDigest(
|
|
privacy_handle,
|
|
privacy_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetCommandAuditDigest(
|
|
response,
|
|
audit_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetTime(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetTime;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string privacy_admin_handle_bytes;
|
|
rc = Serialize_TPMI_RH_ENDORSEMENT(
|
|
privacy_admin_handle,
|
|
&privacy_admin_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(privacy_admin_handle_name.data(),
|
|
privacy_admin_handle_name.size());
|
|
handle_section_bytes += privacy_admin_handle_bytes;
|
|
command_size += privacy_admin_handle_bytes.size();
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetTime(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* time_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetTime;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string time_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
time_info,
|
|
&time_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = time_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
time_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&time_info_bytes,
|
|
time_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetTimeErrorCallback(
|
|
const Tpm::GetTimeResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void GetTimeResponseParser(
|
|
const Tpm::GetTimeResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetTimeErrorCallback, callback);
|
|
TPM2B_ATTEST time_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_GetTime(
|
|
response,
|
|
&time_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
time_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::GetTime(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetTimeResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetTimeErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetTimeResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetTime(
|
|
privacy_admin_handle,
|
|
privacy_admin_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetTimeSync(
|
|
const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
|
|
const std::string& privacy_admin_handle_name,
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
TPM2B_ATTEST* time_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetTime(
|
|
privacy_admin_handle,
|
|
privacy_admin_handle_name,
|
|
sign_handle,
|
|
sign_handle_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetTime(
|
|
response,
|
|
time_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Commit(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const UINT32& param_size,
|
|
const TPM2B_ECC_POINT& p1,
|
|
const TPM2B_SENSITIVE_DATA& s2,
|
|
const TPM2B_ECC_PARAMETER& y2,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Commit;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string param_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
param_size,
|
|
¶m_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string p1_bytes;
|
|
rc = Serialize_TPM2B_ECC_POINT(
|
|
p1,
|
|
&p1_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string s2_bytes;
|
|
rc = Serialize_TPM2B_SENSITIVE_DATA(
|
|
s2,
|
|
&s2_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string y2_bytes;
|
|
rc = Serialize_TPM2B_ECC_PARAMETER(
|
|
y2,
|
|
&y2_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(param_size_bytes.data(),
|
|
param_size_bytes.size());
|
|
parameter_section_bytes += param_size_bytes;
|
|
command_size += param_size_bytes.size();
|
|
hash->Update(p1_bytes.data(),
|
|
p1_bytes.size());
|
|
parameter_section_bytes += p1_bytes;
|
|
command_size += p1_bytes.size();
|
|
hash->Update(s2_bytes.data(),
|
|
s2_bytes.size());
|
|
parameter_section_bytes += s2_bytes;
|
|
command_size += s2_bytes.size();
|
|
hash->Update(y2_bytes.data(),
|
|
y2_bytes.size());
|
|
parameter_section_bytes += y2_bytes;
|
|
command_size += y2_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Commit(
|
|
const std::string& response,
|
|
UINT32* param_size_out,
|
|
TPM2B_ECC_POINT* k,
|
|
TPM2B_ECC_POINT* l,
|
|
TPM2B_ECC_POINT* e,
|
|
UINT16* counter,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Commit;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string param_size_out_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
param_size_out,
|
|
¶m_size_out_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string k_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
k,
|
|
&k_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string l_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
l,
|
|
&l_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string e_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
e,
|
|
&e_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string counter_bytes;
|
|
rc = Parse_UINT16(
|
|
&buffer,
|
|
counter,
|
|
&counter_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void CommitErrorCallback(
|
|
const Tpm::CommitResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
UINT32(),
|
|
TPM2B_ECC_POINT(),
|
|
TPM2B_ECC_POINT(),
|
|
TPM2B_ECC_POINT(),
|
|
UINT16());
|
|
}
|
|
|
|
void CommitResponseParser(
|
|
const Tpm::CommitResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CommitErrorCallback, callback);
|
|
UINT32 param_size_out;
|
|
TPM2B_ECC_POINT k;
|
|
TPM2B_ECC_POINT l;
|
|
TPM2B_ECC_POINT e;
|
|
UINT16 counter;
|
|
TPM_RC rc = Tpm::ParseResponse_Commit(
|
|
response,
|
|
¶m_size_out,
|
|
&k,
|
|
&l,
|
|
&e,
|
|
&counter,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
param_size_out,
|
|
k,
|
|
l,
|
|
e,
|
|
counter);
|
|
}
|
|
|
|
void Tpm::Commit(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const UINT32& param_size,
|
|
const TPM2B_ECC_POINT& p1,
|
|
const TPM2B_SENSITIVE_DATA& s2,
|
|
const TPM2B_ECC_PARAMETER& y2,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const CommitResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CommitErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(CommitResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Commit(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
param_size,
|
|
p1,
|
|
s2,
|
|
y2,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::CommitSync(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const UINT32& param_size,
|
|
const TPM2B_ECC_POINT& p1,
|
|
const TPM2B_SENSITIVE_DATA& s2,
|
|
const TPM2B_ECC_PARAMETER& y2,
|
|
UINT32* param_size_out,
|
|
TPM2B_ECC_POINT* k,
|
|
TPM2B_ECC_POINT* l,
|
|
TPM2B_ECC_POINT* e,
|
|
UINT16* counter,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Commit(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
param_size,
|
|
p1,
|
|
s2,
|
|
y2,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Commit(
|
|
response,
|
|
param_size_out,
|
|
k,
|
|
l,
|
|
e,
|
|
counter,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_EC_Ephemeral(
|
|
const UINT32& param_size,
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_EC_Ephemeral;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string param_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
param_size,
|
|
¶m_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string curve_id_bytes;
|
|
rc = Serialize_TPMI_ECC_CURVE(
|
|
curve_id,
|
|
&curve_id_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(param_size_bytes.data(),
|
|
param_size_bytes.size());
|
|
parameter_section_bytes += param_size_bytes;
|
|
command_size += param_size_bytes.size();
|
|
hash->Update(curve_id_bytes.data(),
|
|
curve_id_bytes.size());
|
|
parameter_section_bytes += curve_id_bytes;
|
|
command_size += curve_id_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_EC_Ephemeral(
|
|
const std::string& response,
|
|
UINT32* param_size_out,
|
|
TPM2B_ECC_POINT* q,
|
|
UINT16* counter,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_EC_Ephemeral;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string param_size_out_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
param_size_out,
|
|
¶m_size_out_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string q_bytes;
|
|
rc = Parse_TPM2B_ECC_POINT(
|
|
&buffer,
|
|
q,
|
|
&q_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string counter_bytes;
|
|
rc = Parse_UINT16(
|
|
&buffer,
|
|
counter,
|
|
&counter_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void EC_EphemeralErrorCallback(
|
|
const Tpm::EC_EphemeralResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
UINT32(),
|
|
TPM2B_ECC_POINT(),
|
|
UINT16());
|
|
}
|
|
|
|
void EC_EphemeralResponseParser(
|
|
const Tpm::EC_EphemeralResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EC_EphemeralErrorCallback, callback);
|
|
UINT32 param_size_out;
|
|
TPM2B_ECC_POINT q;
|
|
UINT16 counter;
|
|
TPM_RC rc = Tpm::ParseResponse_EC_Ephemeral(
|
|
response,
|
|
¶m_size_out,
|
|
&q,
|
|
&counter,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
param_size_out,
|
|
q,
|
|
counter);
|
|
}
|
|
|
|
void Tpm::EC_Ephemeral(
|
|
const UINT32& param_size,
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const EC_EphemeralResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EC_EphemeralErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(EC_EphemeralResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EC_Ephemeral(
|
|
param_size,
|
|
curve_id,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::EC_EphemeralSync(
|
|
const UINT32& param_size,
|
|
const TPMI_ECC_CURVE& curve_id,
|
|
UINT32* param_size_out,
|
|
TPM2B_ECC_POINT* q,
|
|
UINT16* counter,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EC_Ephemeral(
|
|
param_size,
|
|
curve_id,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_EC_Ephemeral(
|
|
response,
|
|
param_size_out,
|
|
q,
|
|
counter,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_VerifySignature(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIGNATURE& signature,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_VerifySignature;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string digest_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
digest,
|
|
&digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Serialize_TPMT_SIGNATURE(
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = digest_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
digest_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(digest_bytes.data(),
|
|
digest_bytes.size());
|
|
parameter_section_bytes += digest_bytes;
|
|
command_size += digest_bytes.size();
|
|
hash->Update(signature_bytes.data(),
|
|
signature_bytes.size());
|
|
parameter_section_bytes += signature_bytes;
|
|
command_size += signature_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_VerifySignature(
|
|
const std::string& response,
|
|
TPMT_TK_VERIFIED* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_VerifySignature;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string validation_bytes;
|
|
rc = Parse_TPMT_TK_VERIFIED(
|
|
&buffer,
|
|
validation,
|
|
&validation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void VerifySignatureErrorCallback(
|
|
const Tpm::VerifySignatureResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMT_TK_VERIFIED());
|
|
}
|
|
|
|
void VerifySignatureResponseParser(
|
|
const Tpm::VerifySignatureResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(VerifySignatureErrorCallback, callback);
|
|
TPMT_TK_VERIFIED validation;
|
|
TPM_RC rc = Tpm::ParseResponse_VerifySignature(
|
|
response,
|
|
&validation,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
validation);
|
|
}
|
|
|
|
void Tpm::VerifySignature(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIGNATURE& signature,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const VerifySignatureResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(VerifySignatureErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(VerifySignatureResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_VerifySignature(
|
|
key_handle,
|
|
key_handle_name,
|
|
digest,
|
|
signature,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::VerifySignatureSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIGNATURE& signature,
|
|
TPMT_TK_VERIFIED* validation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_VerifySignature(
|
|
key_handle,
|
|
key_handle_name,
|
|
digest,
|
|
signature,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_VerifySignature(
|
|
response,
|
|
validation,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Sign(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_HASHCHECK& validation,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Sign;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string digest_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
digest,
|
|
&digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string validation_bytes;
|
|
rc = Serialize_TPMT_TK_HASHCHECK(
|
|
validation,
|
|
&validation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = digest_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
digest_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(digest_bytes.data(),
|
|
digest_bytes.size());
|
|
parameter_section_bytes += digest_bytes;
|
|
command_size += digest_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(validation_bytes.data(),
|
|
validation_bytes.size());
|
|
parameter_section_bytes += validation_bytes;
|
|
command_size += validation_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Sign(
|
|
const std::string& response,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Sign;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SignErrorCallback(
|
|
const Tpm::SignResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void SignResponseParser(
|
|
const Tpm::SignResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SignErrorCallback, callback);
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_Sign(
|
|
response,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::Sign(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_HASHCHECK& validation,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SignResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SignErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SignResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Sign(
|
|
key_handle,
|
|
key_handle_name,
|
|
digest,
|
|
in_scheme,
|
|
validation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SignSync(
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& digest,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const TPMT_TK_HASHCHECK& validation,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Sign(
|
|
key_handle,
|
|
key_handle_name,
|
|
digest,
|
|
in_scheme,
|
|
validation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Sign(
|
|
response,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SetCommandCodeAuditStatus(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_ALG_HASH& audit_alg,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SetCommandCodeAuditStatus;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string audit_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
audit_alg,
|
|
&audit_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string set_list_bytes;
|
|
rc = Serialize_TPML_CC(
|
|
set_list,
|
|
&set_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string clear_list_bytes;
|
|
rc = Serialize_TPML_CC(
|
|
clear_list,
|
|
&clear_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(audit_alg_bytes.data(),
|
|
audit_alg_bytes.size());
|
|
parameter_section_bytes += audit_alg_bytes;
|
|
command_size += audit_alg_bytes.size();
|
|
hash->Update(set_list_bytes.data(),
|
|
set_list_bytes.size());
|
|
parameter_section_bytes += set_list_bytes;
|
|
command_size += set_list_bytes.size();
|
|
hash->Update(clear_list_bytes.data(),
|
|
clear_list_bytes.size());
|
|
parameter_section_bytes += clear_list_bytes;
|
|
command_size += clear_list_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SetCommandCodeAuditStatus(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SetCommandCodeAuditStatus;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SetCommandCodeAuditStatusErrorCallback(
|
|
const Tpm::SetCommandCodeAuditStatusResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void SetCommandCodeAuditStatusResponseParser(
|
|
const Tpm::SetCommandCodeAuditStatusResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetCommandCodeAuditStatusErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_SetCommandCodeAuditStatus(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::SetCommandCodeAuditStatus(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_ALG_HASH& audit_alg,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SetCommandCodeAuditStatusResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetCommandCodeAuditStatusErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SetCommandCodeAuditStatusResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetCommandCodeAuditStatus(
|
|
auth,
|
|
auth_name,
|
|
audit_alg,
|
|
set_list,
|
|
clear_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SetCommandCodeAuditStatusSync(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_ALG_HASH& audit_alg,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetCommandCodeAuditStatus(
|
|
auth,
|
|
auth_name,
|
|
audit_alg,
|
|
set_list,
|
|
clear_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SetCommandCodeAuditStatus(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_Extend(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPML_DIGEST_VALUES& digests,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_Extend;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_handle,
|
|
&pcr_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string digests_bytes;
|
|
rc = Serialize_TPML_DIGEST_VALUES(
|
|
digests,
|
|
&digests_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_handle_name.data(),
|
|
pcr_handle_name.size());
|
|
handle_section_bytes += pcr_handle_bytes;
|
|
command_size += pcr_handle_bytes.size();
|
|
hash->Update(digests_bytes.data(),
|
|
digests_bytes.size());
|
|
parameter_section_bytes += digests_bytes;
|
|
command_size += digests_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_Extend(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_Extend;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_ExtendErrorCallback(
|
|
const Tpm::PCR_ExtendResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PCR_ExtendResponseParser(
|
|
const Tpm::PCR_ExtendResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ExtendErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_Extend(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PCR_Extend(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPML_DIGEST_VALUES& digests,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_ExtendResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ExtendErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_ExtendResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Extend(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
digests,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_ExtendSync(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPML_DIGEST_VALUES& digests,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Extend(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
digests,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_Extend(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_Event(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_EVENT& event_data,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_Event;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_handle,
|
|
&pcr_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string event_data_bytes;
|
|
rc = Serialize_TPM2B_EVENT(
|
|
event_data,
|
|
&event_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = event_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
event_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_handle_name.data(),
|
|
pcr_handle_name.size());
|
|
handle_section_bytes += pcr_handle_bytes;
|
|
command_size += pcr_handle_bytes.size();
|
|
hash->Update(event_data_bytes.data(),
|
|
event_data_bytes.size());
|
|
parameter_section_bytes += event_data_bytes;
|
|
command_size += event_data_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_Event(
|
|
const std::string& response,
|
|
TPML_DIGEST_VALUES* digests,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_Event;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string digests_bytes;
|
|
rc = Parse_TPML_DIGEST_VALUES(
|
|
&buffer,
|
|
digests,
|
|
&digests_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_EventErrorCallback(
|
|
const Tpm::PCR_EventResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPML_DIGEST_VALUES());
|
|
}
|
|
|
|
void PCR_EventResponseParser(
|
|
const Tpm::PCR_EventResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_EventErrorCallback, callback);
|
|
TPML_DIGEST_VALUES digests;
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_Event(
|
|
response,
|
|
&digests,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
digests);
|
|
}
|
|
|
|
void Tpm::PCR_Event(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_EVENT& event_data,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_EventResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_EventErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_EventResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Event(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
event_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_EventSync(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_EVENT& event_data,
|
|
TPML_DIGEST_VALUES* digests,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Event(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
event_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_Event(
|
|
response,
|
|
digests,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_Read(
|
|
const TPML_PCR_SELECTION& pcr_selection_in,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_Read;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_selection_in_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
pcr_selection_in,
|
|
&pcr_selection_in_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_selection_in_bytes.data(),
|
|
pcr_selection_in_bytes.size());
|
|
parameter_section_bytes += pcr_selection_in_bytes;
|
|
command_size += pcr_selection_in_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_Read(
|
|
const std::string& response,
|
|
UINT32* pcr_update_counter,
|
|
TPML_PCR_SELECTION* pcr_selection_out,
|
|
TPML_DIGEST* pcr_values,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_Read;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string pcr_update_counter_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
pcr_update_counter,
|
|
&pcr_update_counter_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_selection_out_bytes;
|
|
rc = Parse_TPML_PCR_SELECTION(
|
|
&buffer,
|
|
pcr_selection_out,
|
|
&pcr_selection_out_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_values_bytes;
|
|
rc = Parse_TPML_DIGEST(
|
|
&buffer,
|
|
pcr_values,
|
|
&pcr_values_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_ReadErrorCallback(
|
|
const Tpm::PCR_ReadResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
UINT32(),
|
|
TPML_PCR_SELECTION(),
|
|
TPML_DIGEST());
|
|
}
|
|
|
|
void PCR_ReadResponseParser(
|
|
const Tpm::PCR_ReadResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ReadErrorCallback, callback);
|
|
UINT32 pcr_update_counter;
|
|
TPML_PCR_SELECTION pcr_selection_out;
|
|
TPML_DIGEST pcr_values;
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_Read(
|
|
response,
|
|
&pcr_update_counter,
|
|
&pcr_selection_out,
|
|
&pcr_values,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
pcr_update_counter,
|
|
pcr_selection_out,
|
|
pcr_values);
|
|
}
|
|
|
|
void Tpm::PCR_Read(
|
|
const TPML_PCR_SELECTION& pcr_selection_in,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_ReadResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ReadErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_ReadResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Read(
|
|
pcr_selection_in,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_ReadSync(
|
|
const TPML_PCR_SELECTION& pcr_selection_in,
|
|
UINT32* pcr_update_counter,
|
|
TPML_PCR_SELECTION* pcr_selection_out,
|
|
TPML_DIGEST* pcr_values,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Read(
|
|
pcr_selection_in,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_Read(
|
|
response,
|
|
pcr_update_counter,
|
|
pcr_selection_out,
|
|
pcr_values,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_Allocate(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPML_PCR_SELECTION& pcr_allocation,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_Allocate;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_allocation_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
pcr_allocation,
|
|
&pcr_allocation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(pcr_allocation_bytes.data(),
|
|
pcr_allocation_bytes.size());
|
|
parameter_section_bytes += pcr_allocation_bytes;
|
|
command_size += pcr_allocation_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_Allocate(
|
|
const std::string& response,
|
|
TPMI_YES_NO* allocation_success,
|
|
UINT32* max_pcr,
|
|
UINT32* size_needed,
|
|
UINT32* size_available,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_Allocate;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string allocation_success_bytes;
|
|
rc = Parse_TPMI_YES_NO(
|
|
&buffer,
|
|
allocation_success,
|
|
&allocation_success_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string max_pcr_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
max_pcr,
|
|
&max_pcr_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string size_needed_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
size_needed,
|
|
&size_needed_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string size_available_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
size_available,
|
|
&size_available_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_AllocateErrorCallback(
|
|
const Tpm::PCR_AllocateResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_YES_NO(),
|
|
UINT32(),
|
|
UINT32(),
|
|
UINT32());
|
|
}
|
|
|
|
void PCR_AllocateResponseParser(
|
|
const Tpm::PCR_AllocateResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_AllocateErrorCallback, callback);
|
|
TPMI_YES_NO allocation_success;
|
|
UINT32 max_pcr;
|
|
UINT32 size_needed;
|
|
UINT32 size_available;
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_Allocate(
|
|
response,
|
|
&allocation_success,
|
|
&max_pcr,
|
|
&size_needed,
|
|
&size_available,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
allocation_success,
|
|
max_pcr,
|
|
size_needed,
|
|
size_available);
|
|
}
|
|
|
|
void Tpm::PCR_Allocate(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPML_PCR_SELECTION& pcr_allocation,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_AllocateResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_AllocateErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_AllocateResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Allocate(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
pcr_allocation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_AllocateSync(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPML_PCR_SELECTION& pcr_allocation,
|
|
TPMI_YES_NO* allocation_success,
|
|
UINT32* max_pcr,
|
|
UINT32* size_needed,
|
|
UINT32* size_available,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Allocate(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
pcr_allocation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_Allocate(
|
|
response,
|
|
allocation_success,
|
|
max_pcr,
|
|
size_needed,
|
|
size_available,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_SetAuthPolicy(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_DH_PCR& pcr_num,
|
|
const std::string& pcr_num_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& policy_digest,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_SetAuthPolicy;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_policy_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
auth_policy,
|
|
&auth_policy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_digest_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
policy_digest,
|
|
&policy_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_num_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_num,
|
|
&pcr_num_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_policy_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_policy_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(pcr_num_name.data(),
|
|
pcr_num_name.size());
|
|
handle_section_bytes += pcr_num_bytes;
|
|
command_size += pcr_num_bytes.size();
|
|
hash->Update(auth_policy_bytes.data(),
|
|
auth_policy_bytes.size());
|
|
parameter_section_bytes += auth_policy_bytes;
|
|
command_size += auth_policy_bytes.size();
|
|
hash->Update(policy_digest_bytes.data(),
|
|
policy_digest_bytes.size());
|
|
parameter_section_bytes += policy_digest_bytes;
|
|
command_size += policy_digest_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_SetAuthPolicy(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_SetAuthPolicy;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_SetAuthPolicyErrorCallback(
|
|
const Tpm::PCR_SetAuthPolicyResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PCR_SetAuthPolicyResponseParser(
|
|
const Tpm::PCR_SetAuthPolicyResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_SetAuthPolicyErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_SetAuthPolicy(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PCR_SetAuthPolicy(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_DH_PCR& pcr_num,
|
|
const std::string& pcr_num_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& policy_digest,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_SetAuthPolicyResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_SetAuthPolicyErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_SetAuthPolicyResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_SetAuthPolicy(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
pcr_num,
|
|
pcr_num_name,
|
|
auth_policy,
|
|
policy_digest,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_SetAuthPolicySync(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_DH_PCR& pcr_num,
|
|
const std::string& pcr_num_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& policy_digest,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_SetAuthPolicy(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
pcr_num,
|
|
pcr_num_name,
|
|
auth_policy,
|
|
policy_digest,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_SetAuthPolicy(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_SetAuthValue(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_DIGEST& auth,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_SetAuthValue;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_handle,
|
|
&pcr_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_handle_name.data(),
|
|
pcr_handle_name.size());
|
|
handle_section_bytes += pcr_handle_bytes;
|
|
command_size += pcr_handle_bytes.size();
|
|
hash->Update(auth_bytes.data(),
|
|
auth_bytes.size());
|
|
parameter_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_SetAuthValue(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_SetAuthValue;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_SetAuthValueErrorCallback(
|
|
const Tpm::PCR_SetAuthValueResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PCR_SetAuthValueResponseParser(
|
|
const Tpm::PCR_SetAuthValueResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_SetAuthValueErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_SetAuthValue(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PCR_SetAuthValue(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_DIGEST& auth,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_SetAuthValueResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_SetAuthValueErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_SetAuthValueResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_SetAuthValue(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_SetAuthValueSync(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
const TPM2B_DIGEST& auth,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_SetAuthValue(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_SetAuthValue(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PCR_Reset(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PCR_Reset;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PCR(
|
|
pcr_handle,
|
|
&pcr_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(pcr_handle_name.data(),
|
|
pcr_handle_name.size());
|
|
handle_section_bytes += pcr_handle_bytes;
|
|
command_size += pcr_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PCR_Reset(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PCR_Reset;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PCR_ResetErrorCallback(
|
|
const Tpm::PCR_ResetResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PCR_ResetResponseParser(
|
|
const Tpm::PCR_ResetResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ResetErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PCR_Reset(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PCR_Reset(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PCR_ResetResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PCR_ResetErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PCR_ResetResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Reset(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PCR_ResetSync(
|
|
const TPMI_DH_PCR& pcr_handle,
|
|
const std::string& pcr_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PCR_Reset(
|
|
pcr_handle,
|
|
pcr_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PCR_Reset(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicySigned(
|
|
const TPMI_DH_OBJECT& auth_object,
|
|
const std::string& auth_object_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
const TPMT_SIGNATURE& auth,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicySigned;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_object_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
auth_object,
|
|
&auth_object_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nonce_tpm_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
nonce_tpm,
|
|
&nonce_tpm_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string cp_hash_a_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
cp_hash_a,
|
|
&cp_hash_a_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ref_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
policy_ref,
|
|
&policy_ref_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string expiration_bytes;
|
|
rc = Serialize_INT32(
|
|
expiration,
|
|
&expiration_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMT_SIGNATURE(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = nonce_tpm_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
nonce_tpm_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_object_name.data(),
|
|
auth_object_name.size());
|
|
handle_section_bytes += auth_object_bytes;
|
|
command_size += auth_object_bytes.size();
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(nonce_tpm_bytes.data(),
|
|
nonce_tpm_bytes.size());
|
|
parameter_section_bytes += nonce_tpm_bytes;
|
|
command_size += nonce_tpm_bytes.size();
|
|
hash->Update(cp_hash_a_bytes.data(),
|
|
cp_hash_a_bytes.size());
|
|
parameter_section_bytes += cp_hash_a_bytes;
|
|
command_size += cp_hash_a_bytes.size();
|
|
hash->Update(policy_ref_bytes.data(),
|
|
policy_ref_bytes.size());
|
|
parameter_section_bytes += policy_ref_bytes;
|
|
command_size += policy_ref_bytes.size();
|
|
hash->Update(expiration_bytes.data(),
|
|
expiration_bytes.size());
|
|
parameter_section_bytes += expiration_bytes;
|
|
command_size += expiration_bytes.size();
|
|
hash->Update(auth_bytes.data(),
|
|
auth_bytes.size());
|
|
parameter_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicySigned(
|
|
const std::string& response,
|
|
TPM2B_TIMEOUT* timeout,
|
|
TPMT_TK_AUTH* policy_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicySigned;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string timeout_bytes;
|
|
rc = Parse_TPM2B_TIMEOUT(
|
|
&buffer,
|
|
timeout,
|
|
&timeout_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ticket_bytes;
|
|
rc = Parse_TPMT_TK_AUTH(
|
|
&buffer,
|
|
policy_ticket,
|
|
&policy_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = timeout_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
timeout_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_TIMEOUT(
|
|
&timeout_bytes,
|
|
timeout,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicySignedErrorCallback(
|
|
const Tpm::PolicySignedResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_TIMEOUT(),
|
|
TPMT_TK_AUTH());
|
|
}
|
|
|
|
void PolicySignedResponseParser(
|
|
const Tpm::PolicySignedResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicySignedErrorCallback, callback);
|
|
TPM2B_TIMEOUT timeout;
|
|
TPMT_TK_AUTH policy_ticket;
|
|
TPM_RC rc = Tpm::ParseResponse_PolicySigned(
|
|
response,
|
|
&timeout,
|
|
&policy_ticket,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
timeout,
|
|
policy_ticket);
|
|
}
|
|
|
|
void Tpm::PolicySigned(
|
|
const TPMI_DH_OBJECT& auth_object,
|
|
const std::string& auth_object_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
const TPMT_SIGNATURE& auth,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicySignedResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicySignedErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicySignedResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicySigned(
|
|
auth_object,
|
|
auth_object_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
nonce_tpm,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
expiration,
|
|
auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicySignedSync(
|
|
const TPMI_DH_OBJECT& auth_object,
|
|
const std::string& auth_object_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
const TPMT_SIGNATURE& auth,
|
|
TPM2B_TIMEOUT* timeout,
|
|
TPMT_TK_AUTH* policy_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicySigned(
|
|
auth_object,
|
|
auth_object_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
nonce_tpm,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
expiration,
|
|
auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicySigned(
|
|
response,
|
|
timeout,
|
|
policy_ticket,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicySecret(
|
|
const TPMI_DH_ENTITY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicySecret;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_DH_ENTITY(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nonce_tpm_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
nonce_tpm,
|
|
&nonce_tpm_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string cp_hash_a_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
cp_hash_a,
|
|
&cp_hash_a_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ref_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
policy_ref,
|
|
&policy_ref_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string expiration_bytes;
|
|
rc = Serialize_INT32(
|
|
expiration,
|
|
&expiration_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = nonce_tpm_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
nonce_tpm_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(nonce_tpm_bytes.data(),
|
|
nonce_tpm_bytes.size());
|
|
parameter_section_bytes += nonce_tpm_bytes;
|
|
command_size += nonce_tpm_bytes.size();
|
|
hash->Update(cp_hash_a_bytes.data(),
|
|
cp_hash_a_bytes.size());
|
|
parameter_section_bytes += cp_hash_a_bytes;
|
|
command_size += cp_hash_a_bytes.size();
|
|
hash->Update(policy_ref_bytes.data(),
|
|
policy_ref_bytes.size());
|
|
parameter_section_bytes += policy_ref_bytes;
|
|
command_size += policy_ref_bytes.size();
|
|
hash->Update(expiration_bytes.data(),
|
|
expiration_bytes.size());
|
|
parameter_section_bytes += expiration_bytes;
|
|
command_size += expiration_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicySecret(
|
|
const std::string& response,
|
|
TPM2B_TIMEOUT* timeout,
|
|
TPMT_TK_AUTH* policy_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicySecret;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string timeout_bytes;
|
|
rc = Parse_TPM2B_TIMEOUT(
|
|
&buffer,
|
|
timeout,
|
|
&timeout_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ticket_bytes;
|
|
rc = Parse_TPMT_TK_AUTH(
|
|
&buffer,
|
|
policy_ticket,
|
|
&policy_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = timeout_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
timeout_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_TIMEOUT(
|
|
&timeout_bytes,
|
|
timeout,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicySecretErrorCallback(
|
|
const Tpm::PolicySecretResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_TIMEOUT(),
|
|
TPMT_TK_AUTH());
|
|
}
|
|
|
|
void PolicySecretResponseParser(
|
|
const Tpm::PolicySecretResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicySecretErrorCallback, callback);
|
|
TPM2B_TIMEOUT timeout;
|
|
TPMT_TK_AUTH policy_ticket;
|
|
TPM_RC rc = Tpm::ParseResponse_PolicySecret(
|
|
response,
|
|
&timeout,
|
|
&policy_ticket,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
timeout,
|
|
policy_ticket);
|
|
}
|
|
|
|
void Tpm::PolicySecret(
|
|
const TPMI_DH_ENTITY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicySecretResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicySecretErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicySecretResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicySecret(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
nonce_tpm,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
expiration,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicySecretSync(
|
|
const TPMI_DH_ENTITY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NONCE& nonce_tpm,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const INT32& expiration,
|
|
TPM2B_TIMEOUT* timeout,
|
|
TPMT_TK_AUTH* policy_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicySecret(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
nonce_tpm,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
expiration,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicySecret(
|
|
response,
|
|
timeout,
|
|
policy_ticket,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyTicket(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_TIMEOUT& timeout,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& auth_name,
|
|
const TPMT_TK_AUTH& ticket,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyTicket;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string timeout_bytes;
|
|
rc = Serialize_TPM2B_TIMEOUT(
|
|
timeout,
|
|
&timeout_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string cp_hash_a_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
cp_hash_a,
|
|
&cp_hash_a_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ref_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
policy_ref,
|
|
&policy_ref_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_name_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
auth_name,
|
|
&auth_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string ticket_bytes;
|
|
rc = Serialize_TPMT_TK_AUTH(
|
|
ticket,
|
|
&ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = timeout_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
timeout_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(timeout_bytes.data(),
|
|
timeout_bytes.size());
|
|
parameter_section_bytes += timeout_bytes;
|
|
command_size += timeout_bytes.size();
|
|
hash->Update(cp_hash_a_bytes.data(),
|
|
cp_hash_a_bytes.size());
|
|
parameter_section_bytes += cp_hash_a_bytes;
|
|
command_size += cp_hash_a_bytes.size();
|
|
hash->Update(policy_ref_bytes.data(),
|
|
policy_ref_bytes.size());
|
|
parameter_section_bytes += policy_ref_bytes;
|
|
command_size += policy_ref_bytes.size();
|
|
hash->Update(auth_name_bytes.data(),
|
|
auth_name_bytes.size());
|
|
parameter_section_bytes += auth_name_bytes;
|
|
command_size += auth_name_bytes.size();
|
|
hash->Update(ticket_bytes.data(),
|
|
ticket_bytes.size());
|
|
parameter_section_bytes += ticket_bytes;
|
|
command_size += ticket_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyTicket(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyTicket;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyTicketErrorCallback(
|
|
const Tpm::PolicyTicketResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyTicketResponseParser(
|
|
const Tpm::PolicyTicketResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyTicketErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyTicket(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyTicket(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_TIMEOUT& timeout,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& auth_name,
|
|
const TPMT_TK_AUTH& ticket,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyTicketResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyTicketErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyTicketResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyTicket(
|
|
policy_session,
|
|
policy_session_name,
|
|
timeout,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
auth_name,
|
|
ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyTicketSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_TIMEOUT& timeout,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& auth_name,
|
|
const TPMT_TK_AUTH& ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyTicket(
|
|
policy_session,
|
|
policy_session_name,
|
|
timeout,
|
|
cp_hash_a,
|
|
policy_ref,
|
|
auth_name,
|
|
ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyTicket(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyOR(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPML_DIGEST& p_hash_list,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyOR;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string p_hash_list_bytes;
|
|
rc = Serialize_TPML_DIGEST(
|
|
p_hash_list,
|
|
&p_hash_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(p_hash_list_bytes.data(),
|
|
p_hash_list_bytes.size());
|
|
parameter_section_bytes += p_hash_list_bytes;
|
|
command_size += p_hash_list_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyOR(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyOR;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyORErrorCallback(
|
|
const Tpm::PolicyORResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyORResponseParser(
|
|
const Tpm::PolicyORResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyORErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyOR(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyOR(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPML_DIGEST& p_hash_list,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyORResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyORErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyORResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyOR(
|
|
policy_session,
|
|
policy_session_name,
|
|
p_hash_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyORSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPML_DIGEST& p_hash_list,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyOR(
|
|
policy_session,
|
|
policy_session_name,
|
|
p_hash_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyOR(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyPCR(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& pcr_digest,
|
|
const TPML_PCR_SELECTION& pcrs,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyPCR;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcr_digest_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
pcr_digest,
|
|
&pcr_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string pcrs_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
pcrs,
|
|
&pcrs_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = pcr_digest_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
pcr_digest_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(pcr_digest_bytes.data(),
|
|
pcr_digest_bytes.size());
|
|
parameter_section_bytes += pcr_digest_bytes;
|
|
command_size += pcr_digest_bytes.size();
|
|
hash->Update(pcrs_bytes.data(),
|
|
pcrs_bytes.size());
|
|
parameter_section_bytes += pcrs_bytes;
|
|
command_size += pcrs_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyPCR(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyPCR;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyPCRErrorCallback(
|
|
const Tpm::PolicyPCRResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyPCRResponseParser(
|
|
const Tpm::PolicyPCRResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPCRErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyPCR(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyPCR(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& pcr_digest,
|
|
const TPML_PCR_SELECTION& pcrs,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyPCRResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPCRErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyPCRResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPCR(
|
|
policy_session,
|
|
policy_session_name,
|
|
pcr_digest,
|
|
pcrs,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyPCRSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& pcr_digest,
|
|
const TPML_PCR_SELECTION& pcrs,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPCR(
|
|
policy_session,
|
|
policy_session_name,
|
|
pcr_digest,
|
|
pcrs,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyPCR(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyLocality(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMA_LOCALITY& locality,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyLocality;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string locality_bytes;
|
|
rc = Serialize_TPMA_LOCALITY(
|
|
locality,
|
|
&locality_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(locality_bytes.data(),
|
|
locality_bytes.size());
|
|
parameter_section_bytes += locality_bytes;
|
|
command_size += locality_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyLocality(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyLocality;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyLocalityErrorCallback(
|
|
const Tpm::PolicyLocalityResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyLocalityResponseParser(
|
|
const Tpm::PolicyLocalityResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyLocalityErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyLocality(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyLocality(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMA_LOCALITY& locality,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyLocalityResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyLocalityErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyLocalityResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyLocality(
|
|
policy_session,
|
|
policy_session_name,
|
|
locality,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyLocalitySync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMA_LOCALITY& locality,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyLocality(
|
|
policy_session,
|
|
policy_session_name,
|
|
locality,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyLocality(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyNV(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyNV;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string operand_b_bytes;
|
|
rc = Serialize_TPM2B_OPERAND(
|
|
operand_b,
|
|
&operand_b_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string offset_bytes;
|
|
rc = Serialize_UINT16(
|
|
offset,
|
|
&offset_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string operation_bytes;
|
|
rc = Serialize_TPM_EO(
|
|
operation,
|
|
&operation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = operand_b_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
operand_b_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(operand_b_bytes.data(),
|
|
operand_b_bytes.size());
|
|
parameter_section_bytes += operand_b_bytes;
|
|
command_size += operand_b_bytes.size();
|
|
hash->Update(offset_bytes.data(),
|
|
offset_bytes.size());
|
|
parameter_section_bytes += offset_bytes;
|
|
command_size += offset_bytes.size();
|
|
hash->Update(operation_bytes.data(),
|
|
operation_bytes.size());
|
|
parameter_section_bytes += operation_bytes;
|
|
command_size += operation_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyNV(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyNV;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyNVErrorCallback(
|
|
const Tpm::PolicyNVResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyNVResponseParser(
|
|
const Tpm::PolicyNVResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNVErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyNV(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyNV(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyNVResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNVErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyNVResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNV(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
operand_b,
|
|
offset,
|
|
operation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyNVSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNV(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
policy_session,
|
|
policy_session_name,
|
|
operand_b,
|
|
offset,
|
|
operation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyNV(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyCounterTimer(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyCounterTimer;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string operand_b_bytes;
|
|
rc = Serialize_TPM2B_OPERAND(
|
|
operand_b,
|
|
&operand_b_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string offset_bytes;
|
|
rc = Serialize_UINT16(
|
|
offset,
|
|
&offset_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string operation_bytes;
|
|
rc = Serialize_TPM_EO(
|
|
operation,
|
|
&operation_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = operand_b_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
operand_b_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(operand_b_bytes.data(),
|
|
operand_b_bytes.size());
|
|
parameter_section_bytes += operand_b_bytes;
|
|
command_size += operand_b_bytes.size();
|
|
hash->Update(offset_bytes.data(),
|
|
offset_bytes.size());
|
|
parameter_section_bytes += offset_bytes;
|
|
command_size += offset_bytes.size();
|
|
hash->Update(operation_bytes.data(),
|
|
operation_bytes.size());
|
|
parameter_section_bytes += operation_bytes;
|
|
command_size += operation_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyCounterTimer(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyCounterTimer;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyCounterTimerErrorCallback(
|
|
const Tpm::PolicyCounterTimerResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyCounterTimerResponseParser(
|
|
const Tpm::PolicyCounterTimerResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCounterTimerErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyCounterTimer(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyCounterTimer(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyCounterTimerResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCounterTimerErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyCounterTimerResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCounterTimer(
|
|
policy_session,
|
|
policy_session_name,
|
|
operand_b,
|
|
offset,
|
|
operation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyCounterTimerSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_OPERAND& operand_b,
|
|
const UINT16& offset,
|
|
const TPM_EO& operation,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCounterTimer(
|
|
policy_session,
|
|
policy_session_name,
|
|
operand_b,
|
|
offset,
|
|
operation,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyCounterTimer(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyCommandCode(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM_CC& code,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyCommandCode;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
code,
|
|
&code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(code_bytes.data(),
|
|
code_bytes.size());
|
|
parameter_section_bytes += code_bytes;
|
|
command_size += code_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyCommandCode(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyCommandCode;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyCommandCodeErrorCallback(
|
|
const Tpm::PolicyCommandCodeResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyCommandCodeResponseParser(
|
|
const Tpm::PolicyCommandCodeResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCommandCodeErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyCommandCode(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyCommandCode(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM_CC& code,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyCommandCodeResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCommandCodeErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyCommandCodeResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCommandCode(
|
|
policy_session,
|
|
policy_session_name,
|
|
code,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyCommandCodeSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM_CC& code,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCommandCode(
|
|
policy_session,
|
|
policy_session_name,
|
|
code,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyCommandCode(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyPhysicalPresence(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyPhysicalPresence;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyPhysicalPresence(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyPhysicalPresence;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyPhysicalPresenceErrorCallback(
|
|
const Tpm::PolicyPhysicalPresenceResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyPhysicalPresenceResponseParser(
|
|
const Tpm::PolicyPhysicalPresenceResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPhysicalPresenceErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyPhysicalPresence(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyPhysicalPresence(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyPhysicalPresenceResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPhysicalPresenceErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyPhysicalPresenceResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPhysicalPresence(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyPhysicalPresenceSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPhysicalPresence(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyPhysicalPresence(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyCpHash(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyCpHash;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string cp_hash_a_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
cp_hash_a,
|
|
&cp_hash_a_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = cp_hash_a_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
cp_hash_a_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(cp_hash_a_bytes.data(),
|
|
cp_hash_a_bytes.size());
|
|
parameter_section_bytes += cp_hash_a_bytes;
|
|
command_size += cp_hash_a_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyCpHash(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyCpHash;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyCpHashErrorCallback(
|
|
const Tpm::PolicyCpHashResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyCpHashResponseParser(
|
|
const Tpm::PolicyCpHashResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCpHashErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyCpHash(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyCpHash(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyCpHashResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyCpHashErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyCpHashResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCpHash(
|
|
policy_session,
|
|
policy_session_name,
|
|
cp_hash_a,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyCpHashSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& cp_hash_a,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyCpHash(
|
|
policy_session,
|
|
policy_session_name,
|
|
cp_hash_a,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyCpHash(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyNameHash(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& name_hash,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyNameHash;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string name_hash_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
name_hash,
|
|
&name_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = name_hash_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
name_hash_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(name_hash_bytes.data(),
|
|
name_hash_bytes.size());
|
|
parameter_section_bytes += name_hash_bytes;
|
|
command_size += name_hash_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyNameHash(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyNameHash;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyNameHashErrorCallback(
|
|
const Tpm::PolicyNameHashResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyNameHashResponseParser(
|
|
const Tpm::PolicyNameHashResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNameHashErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyNameHash(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyNameHash(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& name_hash,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyNameHashResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNameHashErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyNameHashResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNameHash(
|
|
policy_session,
|
|
policy_session_name,
|
|
name_hash,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyNameHashSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& name_hash,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNameHash(
|
|
policy_session,
|
|
policy_session_name,
|
|
name_hash,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyNameHash(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyDuplicationSelect(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NAME& object_name,
|
|
const TPM2B_NAME& new_parent_name,
|
|
const TPMI_YES_NO& include_object,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyDuplicationSelect;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_name_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
object_name,
|
|
&object_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_parent_name_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
new_parent_name,
|
|
&new_parent_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string include_object_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
include_object,
|
|
&include_object_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = object_name_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
object_name_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(object_name_bytes.data(),
|
|
object_name_bytes.size());
|
|
parameter_section_bytes += object_name_bytes;
|
|
command_size += object_name_bytes.size();
|
|
hash->Update(new_parent_name_bytes.data(),
|
|
new_parent_name_bytes.size());
|
|
parameter_section_bytes += new_parent_name_bytes;
|
|
command_size += new_parent_name_bytes.size();
|
|
hash->Update(include_object_bytes.data(),
|
|
include_object_bytes.size());
|
|
parameter_section_bytes += include_object_bytes;
|
|
command_size += include_object_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyDuplicationSelect(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyDuplicationSelect;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyDuplicationSelectErrorCallback(
|
|
const Tpm::PolicyDuplicationSelectResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyDuplicationSelectResponseParser(
|
|
const Tpm::PolicyDuplicationSelectResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyDuplicationSelectErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyDuplicationSelect(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyDuplicationSelect(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NAME& object_name,
|
|
const TPM2B_NAME& new_parent_name,
|
|
const TPMI_YES_NO& include_object,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyDuplicationSelectResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyDuplicationSelectErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyDuplicationSelectResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyDuplicationSelect(
|
|
policy_session,
|
|
policy_session_name,
|
|
object_name,
|
|
new_parent_name,
|
|
include_object,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyDuplicationSelectSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_NAME& object_name,
|
|
const TPM2B_NAME& new_parent_name,
|
|
const TPMI_YES_NO& include_object,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyDuplicationSelect(
|
|
policy_session,
|
|
policy_session_name,
|
|
object_name,
|
|
new_parent_name,
|
|
include_object,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyDuplicationSelect(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyAuthorize(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& approved_policy,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& key_sign,
|
|
const TPMT_TK_VERIFIED& check_ticket,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyAuthorize;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string approved_policy_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
approved_policy,
|
|
&approved_policy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_ref_bytes;
|
|
rc = Serialize_TPM2B_NONCE(
|
|
policy_ref,
|
|
&policy_ref_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_sign_bytes;
|
|
rc = Serialize_TPM2B_NAME(
|
|
key_sign,
|
|
&key_sign_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string check_ticket_bytes;
|
|
rc = Serialize_TPMT_TK_VERIFIED(
|
|
check_ticket,
|
|
&check_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = approved_policy_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
approved_policy_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(approved_policy_bytes.data(),
|
|
approved_policy_bytes.size());
|
|
parameter_section_bytes += approved_policy_bytes;
|
|
command_size += approved_policy_bytes.size();
|
|
hash->Update(policy_ref_bytes.data(),
|
|
policy_ref_bytes.size());
|
|
parameter_section_bytes += policy_ref_bytes;
|
|
command_size += policy_ref_bytes.size();
|
|
hash->Update(key_sign_bytes.data(),
|
|
key_sign_bytes.size());
|
|
parameter_section_bytes += key_sign_bytes;
|
|
command_size += key_sign_bytes.size();
|
|
hash->Update(check_ticket_bytes.data(),
|
|
check_ticket_bytes.size());
|
|
parameter_section_bytes += check_ticket_bytes;
|
|
command_size += check_ticket_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyAuthorize(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyAuthorize;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyAuthorizeErrorCallback(
|
|
const Tpm::PolicyAuthorizeResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyAuthorizeResponseParser(
|
|
const Tpm::PolicyAuthorizeResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyAuthorizeErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyAuthorize(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyAuthorize(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& approved_policy,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& key_sign,
|
|
const TPMT_TK_VERIFIED& check_ticket,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyAuthorizeResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyAuthorizeErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyAuthorizeResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyAuthorize(
|
|
policy_session,
|
|
policy_session_name,
|
|
approved_policy,
|
|
policy_ref,
|
|
key_sign,
|
|
check_ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyAuthorizeSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPM2B_DIGEST& approved_policy,
|
|
const TPM2B_NONCE& policy_ref,
|
|
const TPM2B_NAME& key_sign,
|
|
const TPMT_TK_VERIFIED& check_ticket,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyAuthorize(
|
|
policy_session,
|
|
policy_session_name,
|
|
approved_policy,
|
|
policy_ref,
|
|
key_sign,
|
|
check_ticket,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyAuthorize(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyAuthValue(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyAuthValue;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyAuthValue(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyAuthValue;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyAuthValueErrorCallback(
|
|
const Tpm::PolicyAuthValueResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyAuthValueResponseParser(
|
|
const Tpm::PolicyAuthValueResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyAuthValueErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyAuthValue(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyAuthValue(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyAuthValueResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyAuthValueErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyAuthValueResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyAuthValue(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyAuthValueSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyAuthValue(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyAuthValue(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyPassword(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyPassword;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyPassword(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyPassword;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyPasswordErrorCallback(
|
|
const Tpm::PolicyPasswordResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyPasswordResponseParser(
|
|
const Tpm::PolicyPasswordResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPasswordErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyPassword(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyPassword(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyPasswordResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyPasswordErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyPasswordResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPassword(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyPasswordSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyPassword(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyPassword(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyGetDigest(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyGetDigest;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyGetDigest(
|
|
const std::string& response,
|
|
TPM2B_DIGEST* policy_digest,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyGetDigest;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string policy_digest_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
policy_digest,
|
|
&policy_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = policy_digest_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
policy_digest_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&policy_digest_bytes,
|
|
policy_digest,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyGetDigestErrorCallback(
|
|
const Tpm::PolicyGetDigestResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_DIGEST());
|
|
}
|
|
|
|
void PolicyGetDigestResponseParser(
|
|
const Tpm::PolicyGetDigestResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyGetDigestErrorCallback, callback);
|
|
TPM2B_DIGEST policy_digest;
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyGetDigest(
|
|
response,
|
|
&policy_digest,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
policy_digest);
|
|
}
|
|
|
|
void Tpm::PolicyGetDigest(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyGetDigestResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyGetDigestErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyGetDigestResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyGetDigest(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyGetDigestSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
TPM2B_DIGEST* policy_digest,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyGetDigest(
|
|
policy_session,
|
|
policy_session_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyGetDigest(
|
|
response,
|
|
policy_digest,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PolicyNvWritten(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMI_YES_NO& written_set,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PolicyNvWritten;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string policy_session_bytes;
|
|
rc = Serialize_TPMI_SH_POLICY(
|
|
policy_session,
|
|
&policy_session_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string written_set_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
written_set,
|
|
&written_set_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(policy_session_name.data(),
|
|
policy_session_name.size());
|
|
handle_section_bytes += policy_session_bytes;
|
|
command_size += policy_session_bytes.size();
|
|
hash->Update(written_set_bytes.data(),
|
|
written_set_bytes.size());
|
|
parameter_section_bytes += written_set_bytes;
|
|
command_size += written_set_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PolicyNvWritten(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PolicyNvWritten;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PolicyNvWrittenErrorCallback(
|
|
const Tpm::PolicyNvWrittenResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PolicyNvWrittenResponseParser(
|
|
const Tpm::PolicyNvWrittenResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNvWrittenErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PolicyNvWritten(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PolicyNvWritten(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMI_YES_NO& written_set,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PolicyNvWrittenResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PolicyNvWrittenErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PolicyNvWrittenResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNvWritten(
|
|
policy_session,
|
|
policy_session_name,
|
|
written_set,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PolicyNvWrittenSync(
|
|
const TPMI_SH_POLICY& policy_session,
|
|
const std::string& policy_session_name,
|
|
const TPMI_YES_NO& written_set,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PolicyNvWritten(
|
|
policy_session,
|
|
policy_session_name,
|
|
written_set,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PolicyNvWritten(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_CreatePrimary(
|
|
const TPMI_RH_HIERARCHY& primary_handle,
|
|
const std::string& primary_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_CreatePrimary;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string primary_handle_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
primary_handle,
|
|
&primary_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_sensitive_bytes;
|
|
rc = Serialize_TPM2B_SENSITIVE_CREATE(
|
|
in_sensitive,
|
|
&in_sensitive_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_public_bytes;
|
|
rc = Serialize_TPM2B_PUBLIC(
|
|
in_public,
|
|
&in_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string outside_info_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
outside_info,
|
|
&outside_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_pcr_bytes;
|
|
rc = Serialize_TPML_PCR_SELECTION(
|
|
creation_pcr,
|
|
&creation_pcr_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = in_sensitive_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
in_sensitive_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(primary_handle_name.data(),
|
|
primary_handle_name.size());
|
|
handle_section_bytes += primary_handle_bytes;
|
|
command_size += primary_handle_bytes.size();
|
|
hash->Update(in_sensitive_bytes.data(),
|
|
in_sensitive_bytes.size());
|
|
parameter_section_bytes += in_sensitive_bytes;
|
|
command_size += in_sensitive_bytes.size();
|
|
hash->Update(in_public_bytes.data(),
|
|
in_public_bytes.size());
|
|
parameter_section_bytes += in_public_bytes;
|
|
command_size += in_public_bytes.size();
|
|
hash->Update(outside_info_bytes.data(),
|
|
outside_info_bytes.size());
|
|
parameter_section_bytes += outside_info_bytes;
|
|
command_size += outside_info_bytes.size();
|
|
hash->Update(creation_pcr_bytes.data(),
|
|
creation_pcr_bytes.size());
|
|
parameter_section_bytes += creation_pcr_bytes;
|
|
command_size += creation_pcr_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_CreatePrimary(
|
|
const std::string& response,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_CREATION_DATA* creation_data,
|
|
TPM2B_DIGEST* creation_hash,
|
|
TPMT_TK_CREATION* creation_ticket,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Parse_TPM_HANDLE(
|
|
&buffer,
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_CreatePrimary;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string out_public_bytes;
|
|
rc = Parse_TPM2B_PUBLIC(
|
|
&buffer,
|
|
out_public,
|
|
&out_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_data_bytes;
|
|
rc = Parse_TPM2B_CREATION_DATA(
|
|
&buffer,
|
|
creation_data,
|
|
&creation_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_hash_bytes;
|
|
rc = Parse_TPM2B_DIGEST(
|
|
&buffer,
|
|
creation_hash,
|
|
&creation_hash_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string creation_ticket_bytes;
|
|
rc = Parse_TPMT_TK_CREATION(
|
|
&buffer,
|
|
creation_ticket,
|
|
&creation_ticket_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
name,
|
|
&name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = out_public_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
out_public_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_PUBLIC(
|
|
&out_public_bytes,
|
|
out_public,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void CreatePrimaryErrorCallback(
|
|
const Tpm::CreatePrimaryResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM_HANDLE(),
|
|
TPM2B_PUBLIC(),
|
|
TPM2B_CREATION_DATA(),
|
|
TPM2B_DIGEST(),
|
|
TPMT_TK_CREATION(),
|
|
TPM2B_NAME());
|
|
}
|
|
|
|
void CreatePrimaryResponseParser(
|
|
const Tpm::CreatePrimaryResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CreatePrimaryErrorCallback, callback);
|
|
TPM_HANDLE object_handle;
|
|
TPM2B_PUBLIC out_public;
|
|
TPM2B_CREATION_DATA creation_data;
|
|
TPM2B_DIGEST creation_hash;
|
|
TPMT_TK_CREATION creation_ticket;
|
|
TPM2B_NAME name;
|
|
TPM_RC rc = Tpm::ParseResponse_CreatePrimary(
|
|
response,
|
|
&object_handle,
|
|
&out_public,
|
|
&creation_data,
|
|
&creation_hash,
|
|
&creation_ticket,
|
|
&name,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
object_handle,
|
|
out_public,
|
|
creation_data,
|
|
creation_hash,
|
|
creation_ticket,
|
|
name);
|
|
}
|
|
|
|
void Tpm::CreatePrimary(
|
|
const TPMI_RH_HIERARCHY& primary_handle,
|
|
const std::string& primary_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const CreatePrimaryResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(CreatePrimaryErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(CreatePrimaryResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_CreatePrimary(
|
|
primary_handle,
|
|
primary_handle_name,
|
|
in_sensitive,
|
|
in_public,
|
|
outside_info,
|
|
creation_pcr,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::CreatePrimarySync(
|
|
const TPMI_RH_HIERARCHY& primary_handle,
|
|
const std::string& primary_handle_name,
|
|
const TPM2B_SENSITIVE_CREATE& in_sensitive,
|
|
const TPM2B_PUBLIC& in_public,
|
|
const TPM2B_DATA& outside_info,
|
|
const TPML_PCR_SELECTION& creation_pcr,
|
|
TPM_HANDLE* object_handle,
|
|
TPM2B_PUBLIC* out_public,
|
|
TPM2B_CREATION_DATA* creation_data,
|
|
TPM2B_DIGEST* creation_hash,
|
|
TPMT_TK_CREATION* creation_ticket,
|
|
TPM2B_NAME* name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_CreatePrimary(
|
|
primary_handle,
|
|
primary_handle_name,
|
|
in_sensitive,
|
|
in_public,
|
|
outside_info,
|
|
creation_pcr,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_CreatePrimary(
|
|
response,
|
|
object_handle,
|
|
out_public,
|
|
creation_data,
|
|
creation_hash,
|
|
creation_ticket,
|
|
name,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_HierarchyControl(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_ENABLES& enable,
|
|
const TPMI_YES_NO& state,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_HierarchyControl;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string enable_bytes;
|
|
rc = Serialize_TPMI_RH_ENABLES(
|
|
enable,
|
|
&enable_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string state_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
state,
|
|
&state_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(enable_bytes.data(),
|
|
enable_bytes.size());
|
|
parameter_section_bytes += enable_bytes;
|
|
command_size += enable_bytes.size();
|
|
hash->Update(state_bytes.data(),
|
|
state_bytes.size());
|
|
parameter_section_bytes += state_bytes;
|
|
command_size += state_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_HierarchyControl(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_HierarchyControl;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HierarchyControlErrorCallback(
|
|
const Tpm::HierarchyControlResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void HierarchyControlResponseParser(
|
|
const Tpm::HierarchyControlResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HierarchyControlErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_HierarchyControl(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::HierarchyControl(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_ENABLES& enable,
|
|
const TPMI_YES_NO& state,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HierarchyControlResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HierarchyControlErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HierarchyControlResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HierarchyControl(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
enable,
|
|
state,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HierarchyControlSync(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_ENABLES& enable,
|
|
const TPMI_YES_NO& state,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HierarchyControl(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
enable,
|
|
state,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_HierarchyControl(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SetPrimaryPolicy(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SetPrimaryPolicy;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_policy_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
auth_policy,
|
|
&auth_policy_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string hash_alg_bytes;
|
|
rc = Serialize_TPMI_ALG_HASH(
|
|
hash_alg,
|
|
&hash_alg_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_policy_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_policy_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(auth_policy_bytes.data(),
|
|
auth_policy_bytes.size());
|
|
parameter_section_bytes += auth_policy_bytes;
|
|
command_size += auth_policy_bytes.size();
|
|
hash->Update(hash_alg_bytes.data(),
|
|
hash_alg_bytes.size());
|
|
parameter_section_bytes += hash_alg_bytes;
|
|
command_size += hash_alg_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SetPrimaryPolicy(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SetPrimaryPolicy;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SetPrimaryPolicyErrorCallback(
|
|
const Tpm::SetPrimaryPolicyResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void SetPrimaryPolicyResponseParser(
|
|
const Tpm::SetPrimaryPolicyResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetPrimaryPolicyErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_SetPrimaryPolicy(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::SetPrimaryPolicy(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SetPrimaryPolicyResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetPrimaryPolicyErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SetPrimaryPolicyResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetPrimaryPolicy(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
auth_policy,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SetPrimaryPolicySync(
|
|
const TPMI_RH_HIERARCHY& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_DIGEST& auth_policy,
|
|
const TPMI_ALG_HASH& hash_alg,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetPrimaryPolicy(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
auth_policy,
|
|
hash_alg,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SetPrimaryPolicy(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ChangePPS(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ChangePPS;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ChangePPS(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ChangePPS;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ChangePPSErrorCallback(
|
|
const Tpm::ChangePPSResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ChangePPSResponseParser(
|
|
const Tpm::ChangePPSResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ChangePPSErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_ChangePPS(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::ChangePPS(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ChangePPSResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ChangePPSErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ChangePPSResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ChangePPS(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ChangePPSSync(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ChangePPS(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ChangePPS(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ChangeEPS(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ChangeEPS;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ChangeEPS(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ChangeEPS;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ChangeEPSErrorCallback(
|
|
const Tpm::ChangeEPSResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ChangeEPSResponseParser(
|
|
const Tpm::ChangeEPSResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ChangeEPSErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_ChangeEPS(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::ChangeEPS(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ChangeEPSResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ChangeEPSErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ChangeEPSResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ChangeEPS(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ChangeEPSSync(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ChangeEPS(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ChangeEPS(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_Clear(
|
|
const TPMI_RH_CLEAR& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_Clear;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_CLEAR(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_Clear(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_Clear;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ClearErrorCallback(
|
|
const Tpm::ClearResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ClearResponseParser(
|
|
const Tpm::ClearResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClearErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_Clear(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::Clear(
|
|
const TPMI_RH_CLEAR& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ClearResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClearErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ClearResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Clear(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ClearSync(
|
|
const TPMI_RH_CLEAR& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_Clear(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_Clear(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ClearControl(
|
|
const TPMI_RH_CLEAR& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_YES_NO& disable,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ClearControl;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_CLEAR(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string disable_bytes;
|
|
rc = Serialize_TPMI_YES_NO(
|
|
disable,
|
|
&disable_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(disable_bytes.data(),
|
|
disable_bytes.size());
|
|
parameter_section_bytes += disable_bytes;
|
|
command_size += disable_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ClearControl(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ClearControl;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ClearControlErrorCallback(
|
|
const Tpm::ClearControlResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ClearControlResponseParser(
|
|
const Tpm::ClearControlResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClearControlErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_ClearControl(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::ClearControl(
|
|
const TPMI_RH_CLEAR& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_YES_NO& disable,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ClearControlResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClearControlErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ClearControlResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClearControl(
|
|
auth,
|
|
auth_name,
|
|
disable,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ClearControlSync(
|
|
const TPMI_RH_CLEAR& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_YES_NO& disable,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClearControl(
|
|
auth,
|
|
auth_name,
|
|
disable,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ClearControl(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_HierarchyChangeAuth(
|
|
const TPMI_RH_HIERARCHY_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_HierarchyChangeAuth;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_HIERARCHY_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
new_auth,
|
|
&new_auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = new_auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
new_auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(new_auth_bytes.data(),
|
|
new_auth_bytes.size());
|
|
parameter_section_bytes += new_auth_bytes;
|
|
command_size += new_auth_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_HierarchyChangeAuth(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_HierarchyChangeAuth;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void HierarchyChangeAuthErrorCallback(
|
|
const Tpm::HierarchyChangeAuthResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void HierarchyChangeAuthResponseParser(
|
|
const Tpm::HierarchyChangeAuthResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HierarchyChangeAuthErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_HierarchyChangeAuth(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::HierarchyChangeAuth(
|
|
const TPMI_RH_HIERARCHY_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const HierarchyChangeAuthResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(HierarchyChangeAuthErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(HierarchyChangeAuthResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HierarchyChangeAuth(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::HierarchyChangeAuthSync(
|
|
const TPMI_RH_HIERARCHY_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_HierarchyChangeAuth(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_HierarchyChangeAuth(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_DictionaryAttackLockReset(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_DictionaryAttackLockReset;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string lock_handle_bytes;
|
|
rc = Serialize_TPMI_RH_LOCKOUT(
|
|
lock_handle,
|
|
&lock_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(lock_handle_name.data(),
|
|
lock_handle_name.size());
|
|
handle_section_bytes += lock_handle_bytes;
|
|
command_size += lock_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_DictionaryAttackLockReset(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_DictionaryAttackLockReset;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void DictionaryAttackLockResetErrorCallback(
|
|
const Tpm::DictionaryAttackLockResetResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void DictionaryAttackLockResetResponseParser(
|
|
const Tpm::DictionaryAttackLockResetResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DictionaryAttackLockResetErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_DictionaryAttackLockReset(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::DictionaryAttackLockReset(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const DictionaryAttackLockResetResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DictionaryAttackLockResetErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(DictionaryAttackLockResetResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_DictionaryAttackLockReset(
|
|
lock_handle,
|
|
lock_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::DictionaryAttackLockResetSync(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_DictionaryAttackLockReset(
|
|
lock_handle,
|
|
lock_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_DictionaryAttackLockReset(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_DictionaryAttackParameters(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
const UINT32& new_max_tries,
|
|
const UINT32& new_recovery_time,
|
|
const UINT32& lockout_recovery,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_DictionaryAttackParameters;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string lock_handle_bytes;
|
|
rc = Serialize_TPMI_RH_LOCKOUT(
|
|
lock_handle,
|
|
&lock_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_max_tries_bytes;
|
|
rc = Serialize_UINT32(
|
|
new_max_tries,
|
|
&new_max_tries_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_recovery_time_bytes;
|
|
rc = Serialize_UINT32(
|
|
new_recovery_time,
|
|
&new_recovery_time_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string lockout_recovery_bytes;
|
|
rc = Serialize_UINT32(
|
|
lockout_recovery,
|
|
&lockout_recovery_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(lock_handle_name.data(),
|
|
lock_handle_name.size());
|
|
handle_section_bytes += lock_handle_bytes;
|
|
command_size += lock_handle_bytes.size();
|
|
hash->Update(new_max_tries_bytes.data(),
|
|
new_max_tries_bytes.size());
|
|
parameter_section_bytes += new_max_tries_bytes;
|
|
command_size += new_max_tries_bytes.size();
|
|
hash->Update(new_recovery_time_bytes.data(),
|
|
new_recovery_time_bytes.size());
|
|
parameter_section_bytes += new_recovery_time_bytes;
|
|
command_size += new_recovery_time_bytes.size();
|
|
hash->Update(lockout_recovery_bytes.data(),
|
|
lockout_recovery_bytes.size());
|
|
parameter_section_bytes += lockout_recovery_bytes;
|
|
command_size += lockout_recovery_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_DictionaryAttackParameters(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_DictionaryAttackParameters;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void DictionaryAttackParametersErrorCallback(
|
|
const Tpm::DictionaryAttackParametersResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void DictionaryAttackParametersResponseParser(
|
|
const Tpm::DictionaryAttackParametersResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DictionaryAttackParametersErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_DictionaryAttackParameters(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::DictionaryAttackParameters(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
const UINT32& new_max_tries,
|
|
const UINT32& new_recovery_time,
|
|
const UINT32& lockout_recovery,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const DictionaryAttackParametersResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(DictionaryAttackParametersErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(DictionaryAttackParametersResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_DictionaryAttackParameters(
|
|
lock_handle,
|
|
lock_handle_name,
|
|
new_max_tries,
|
|
new_recovery_time,
|
|
lockout_recovery,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::DictionaryAttackParametersSync(
|
|
const TPMI_RH_LOCKOUT& lock_handle,
|
|
const std::string& lock_handle_name,
|
|
const UINT32& new_max_tries,
|
|
const UINT32& new_recovery_time,
|
|
const UINT32& lockout_recovery,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_DictionaryAttackParameters(
|
|
lock_handle,
|
|
lock_handle_name,
|
|
new_max_tries,
|
|
new_recovery_time,
|
|
lockout_recovery,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_DictionaryAttackParameters(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_PP_Commands(
|
|
const TPMI_RH_PLATFORM& auth,
|
|
const std::string& auth_name,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_PP_Commands;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string set_list_bytes;
|
|
rc = Serialize_TPML_CC(
|
|
set_list,
|
|
&set_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string clear_list_bytes;
|
|
rc = Serialize_TPML_CC(
|
|
clear_list,
|
|
&clear_list_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(set_list_bytes.data(),
|
|
set_list_bytes.size());
|
|
parameter_section_bytes += set_list_bytes;
|
|
command_size += set_list_bytes.size();
|
|
hash->Update(clear_list_bytes.data(),
|
|
clear_list_bytes.size());
|
|
parameter_section_bytes += clear_list_bytes;
|
|
command_size += clear_list_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_PP_Commands(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_PP_Commands;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void PP_CommandsErrorCallback(
|
|
const Tpm::PP_CommandsResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void PP_CommandsResponseParser(
|
|
const Tpm::PP_CommandsResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PP_CommandsErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_PP_Commands(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::PP_Commands(
|
|
const TPMI_RH_PLATFORM& auth,
|
|
const std::string& auth_name,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const PP_CommandsResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(PP_CommandsErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(PP_CommandsResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PP_Commands(
|
|
auth,
|
|
auth_name,
|
|
set_list,
|
|
clear_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::PP_CommandsSync(
|
|
const TPMI_RH_PLATFORM& auth,
|
|
const std::string& auth_name,
|
|
const TPML_CC& set_list,
|
|
const TPML_CC& clear_list,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_PP_Commands(
|
|
auth,
|
|
auth_name,
|
|
set_list,
|
|
clear_list,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_PP_Commands(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_SetAlgorithmSet(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const UINT32& algorithm_set,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_SetAlgorithmSet;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string algorithm_set_bytes;
|
|
rc = Serialize_UINT32(
|
|
algorithm_set,
|
|
&algorithm_set_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(algorithm_set_bytes.data(),
|
|
algorithm_set_bytes.size());
|
|
parameter_section_bytes += algorithm_set_bytes;
|
|
command_size += algorithm_set_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_SetAlgorithmSet(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_SetAlgorithmSet;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void SetAlgorithmSetErrorCallback(
|
|
const Tpm::SetAlgorithmSetResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void SetAlgorithmSetResponseParser(
|
|
const Tpm::SetAlgorithmSetResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetAlgorithmSetErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_SetAlgorithmSet(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::SetAlgorithmSet(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const UINT32& algorithm_set,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const SetAlgorithmSetResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(SetAlgorithmSetErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(SetAlgorithmSetResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetAlgorithmSet(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
algorithm_set,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::SetAlgorithmSetSync(
|
|
const TPMI_RH_PLATFORM& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const UINT32& algorithm_set,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_SetAlgorithmSet(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
algorithm_set,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_SetAlgorithmSet(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_FieldUpgradeStart(
|
|
const TPMI_RH_PLATFORM& authorization,
|
|
const std::string& authorization_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& fu_digest,
|
|
const TPMT_SIGNATURE& manifest_signature,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_FieldUpgradeStart;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
authorization,
|
|
&authorization_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string key_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
key_handle,
|
|
&key_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string fu_digest_bytes;
|
|
rc = Serialize_TPM2B_DIGEST(
|
|
fu_digest,
|
|
&fu_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string manifest_signature_bytes;
|
|
rc = Serialize_TPMT_SIGNATURE(
|
|
manifest_signature,
|
|
&manifest_signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = fu_digest_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
fu_digest_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(authorization_name.data(),
|
|
authorization_name.size());
|
|
handle_section_bytes += authorization_bytes;
|
|
command_size += authorization_bytes.size();
|
|
hash->Update(key_handle_name.data(),
|
|
key_handle_name.size());
|
|
handle_section_bytes += key_handle_bytes;
|
|
command_size += key_handle_bytes.size();
|
|
hash->Update(fu_digest_bytes.data(),
|
|
fu_digest_bytes.size());
|
|
parameter_section_bytes += fu_digest_bytes;
|
|
command_size += fu_digest_bytes.size();
|
|
hash->Update(manifest_signature_bytes.data(),
|
|
manifest_signature_bytes.size());
|
|
parameter_section_bytes += manifest_signature_bytes;
|
|
command_size += manifest_signature_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_FieldUpgradeStart(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_FieldUpgradeStart;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void FieldUpgradeStartErrorCallback(
|
|
const Tpm::FieldUpgradeStartResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void FieldUpgradeStartResponseParser(
|
|
const Tpm::FieldUpgradeStartResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FieldUpgradeStartErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_FieldUpgradeStart(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::FieldUpgradeStart(
|
|
const TPMI_RH_PLATFORM& authorization,
|
|
const std::string& authorization_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& fu_digest,
|
|
const TPMT_SIGNATURE& manifest_signature,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const FieldUpgradeStartResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FieldUpgradeStartErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(FieldUpgradeStartResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FieldUpgradeStart(
|
|
authorization,
|
|
authorization_name,
|
|
key_handle,
|
|
key_handle_name,
|
|
fu_digest,
|
|
manifest_signature,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::FieldUpgradeStartSync(
|
|
const TPMI_RH_PLATFORM& authorization,
|
|
const std::string& authorization_name,
|
|
const TPMI_DH_OBJECT& key_handle,
|
|
const std::string& key_handle_name,
|
|
const TPM2B_DIGEST& fu_digest,
|
|
const TPMT_SIGNATURE& manifest_signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FieldUpgradeStart(
|
|
authorization,
|
|
authorization_name,
|
|
key_handle,
|
|
key_handle_name,
|
|
fu_digest,
|
|
manifest_signature,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_FieldUpgradeStart(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_FieldUpgradeData(
|
|
const TPM2B_MAX_BUFFER& fu_data,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_FieldUpgradeData;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string fu_data_bytes;
|
|
rc = Serialize_TPM2B_MAX_BUFFER(
|
|
fu_data,
|
|
&fu_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = fu_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
fu_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(fu_data_bytes.data(),
|
|
fu_data_bytes.size());
|
|
parameter_section_bytes += fu_data_bytes;
|
|
command_size += fu_data_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_FieldUpgradeData(
|
|
const std::string& response,
|
|
TPMT_HA* next_digest,
|
|
TPMT_HA* first_digest,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_FieldUpgradeData;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string next_digest_bytes;
|
|
rc = Parse_TPMT_HA(
|
|
&buffer,
|
|
next_digest,
|
|
&next_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string first_digest_bytes;
|
|
rc = Parse_TPMT_HA(
|
|
&buffer,
|
|
first_digest,
|
|
&first_digest_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void FieldUpgradeDataErrorCallback(
|
|
const Tpm::FieldUpgradeDataResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMT_HA(),
|
|
TPMT_HA());
|
|
}
|
|
|
|
void FieldUpgradeDataResponseParser(
|
|
const Tpm::FieldUpgradeDataResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FieldUpgradeDataErrorCallback, callback);
|
|
TPMT_HA next_digest;
|
|
TPMT_HA first_digest;
|
|
TPM_RC rc = Tpm::ParseResponse_FieldUpgradeData(
|
|
response,
|
|
&next_digest,
|
|
&first_digest,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
next_digest,
|
|
first_digest);
|
|
}
|
|
|
|
void Tpm::FieldUpgradeData(
|
|
const TPM2B_MAX_BUFFER& fu_data,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const FieldUpgradeDataResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FieldUpgradeDataErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(FieldUpgradeDataResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FieldUpgradeData(
|
|
fu_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::FieldUpgradeDataSync(
|
|
const TPM2B_MAX_BUFFER& fu_data,
|
|
TPMT_HA* next_digest,
|
|
TPMT_HA* first_digest,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FieldUpgradeData(
|
|
fu_data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_FieldUpgradeData(
|
|
response,
|
|
next_digest,
|
|
first_digest,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_FirmwareRead(
|
|
const UINT32& sequence_number,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_FirmwareRead;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sequence_number_bytes;
|
|
rc = Serialize_UINT32(
|
|
sequence_number,
|
|
&sequence_number_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sequence_number_bytes.data(),
|
|
sequence_number_bytes.size());
|
|
parameter_section_bytes += sequence_number_bytes;
|
|
command_size += sequence_number_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_FirmwareRead(
|
|
const std::string& response,
|
|
TPM2B_MAX_BUFFER* fu_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_FirmwareRead;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string fu_data_bytes;
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&buffer,
|
|
fu_data,
|
|
&fu_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = fu_data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
fu_data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_MAX_BUFFER(
|
|
&fu_data_bytes,
|
|
fu_data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void FirmwareReadErrorCallback(
|
|
const Tpm::FirmwareReadResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_MAX_BUFFER());
|
|
}
|
|
|
|
void FirmwareReadResponseParser(
|
|
const Tpm::FirmwareReadResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FirmwareReadErrorCallback, callback);
|
|
TPM2B_MAX_BUFFER fu_data;
|
|
TPM_RC rc = Tpm::ParseResponse_FirmwareRead(
|
|
response,
|
|
&fu_data,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
fu_data);
|
|
}
|
|
|
|
void Tpm::FirmwareRead(
|
|
const UINT32& sequence_number,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const FirmwareReadResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FirmwareReadErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(FirmwareReadResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FirmwareRead(
|
|
sequence_number,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::FirmwareReadSync(
|
|
const UINT32& sequence_number,
|
|
TPM2B_MAX_BUFFER* fu_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FirmwareRead(
|
|
sequence_number,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_FirmwareRead(
|
|
response,
|
|
fu_data,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ContextSave(
|
|
const TPMI_DH_CONTEXT& save_handle,
|
|
const std::string& save_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ContextSave;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string save_handle_bytes;
|
|
rc = Serialize_TPMI_DH_CONTEXT(
|
|
save_handle,
|
|
&save_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(save_handle_name.data(),
|
|
save_handle_name.size());
|
|
handle_section_bytes += save_handle_bytes;
|
|
command_size += save_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ContextSave(
|
|
const std::string& response,
|
|
TPMS_CONTEXT* context,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ContextSave;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string context_bytes;
|
|
rc = Parse_TPMS_CONTEXT(
|
|
&buffer,
|
|
context,
|
|
&context_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ContextSaveErrorCallback(
|
|
const Tpm::ContextSaveResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMS_CONTEXT());
|
|
}
|
|
|
|
void ContextSaveResponseParser(
|
|
const Tpm::ContextSaveResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ContextSaveErrorCallback, callback);
|
|
TPMS_CONTEXT context;
|
|
TPM_RC rc = Tpm::ParseResponse_ContextSave(
|
|
response,
|
|
&context,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
context);
|
|
}
|
|
|
|
void Tpm::ContextSave(
|
|
const TPMI_DH_CONTEXT& save_handle,
|
|
const std::string& save_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ContextSaveResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ContextSaveErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ContextSaveResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ContextSave(
|
|
save_handle,
|
|
save_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ContextSaveSync(
|
|
const TPMI_DH_CONTEXT& save_handle,
|
|
const std::string& save_handle_name,
|
|
TPMS_CONTEXT* context,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ContextSave(
|
|
save_handle,
|
|
save_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ContextSave(
|
|
response,
|
|
context,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ContextLoad(
|
|
const TPMS_CONTEXT& context,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ContextLoad;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string context_bytes;
|
|
rc = Serialize_TPMS_CONTEXT(
|
|
context,
|
|
&context_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(context_bytes.data(),
|
|
context_bytes.size());
|
|
parameter_section_bytes += context_bytes;
|
|
command_size += context_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ContextLoad(
|
|
const std::string& response,
|
|
TPMI_DH_CONTEXT* loaded_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
std::string loaded_handle_bytes;
|
|
rc = Parse_TPMI_DH_CONTEXT(
|
|
&buffer,
|
|
loaded_handle,
|
|
&loaded_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ContextLoad;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ContextLoadErrorCallback(
|
|
const Tpm::ContextLoadResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_DH_CONTEXT());
|
|
}
|
|
|
|
void ContextLoadResponseParser(
|
|
const Tpm::ContextLoadResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ContextLoadErrorCallback, callback);
|
|
TPMI_DH_CONTEXT loaded_handle;
|
|
TPM_RC rc = Tpm::ParseResponse_ContextLoad(
|
|
response,
|
|
&loaded_handle,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
loaded_handle);
|
|
}
|
|
|
|
void Tpm::ContextLoad(
|
|
const TPMS_CONTEXT& context,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ContextLoadResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ContextLoadErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ContextLoadResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ContextLoad(
|
|
context,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ContextLoadSync(
|
|
const TPMS_CONTEXT& context,
|
|
TPMI_DH_CONTEXT* loaded_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ContextLoad(
|
|
context,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ContextLoad(
|
|
response,
|
|
loaded_handle,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_FlushContext(
|
|
const TPMI_DH_CONTEXT& flush_handle,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_FlushContext;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string flush_handle_bytes;
|
|
rc = Serialize_TPMI_DH_CONTEXT(
|
|
flush_handle,
|
|
&flush_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(flush_handle_bytes.data(),
|
|
flush_handle_bytes.size());
|
|
parameter_section_bytes += flush_handle_bytes;
|
|
command_size += flush_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_FlushContext(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_FlushContext;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void FlushContextErrorCallback(
|
|
const Tpm::FlushContextResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void FlushContextResponseParser(
|
|
const Tpm::FlushContextResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FlushContextErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_FlushContext(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::FlushContext(
|
|
const TPMI_DH_CONTEXT& flush_handle,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const FlushContextResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(FlushContextErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(FlushContextResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FlushContext(
|
|
flush_handle,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::FlushContextSync(
|
|
const TPMI_DH_CONTEXT& flush_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_FlushContext(
|
|
flush_handle,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_FlushContext(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_EvictControl(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_PERSISTENT& persistent_handle,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_EvictControl;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string object_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
object_handle,
|
|
&object_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string persistent_handle_bytes;
|
|
rc = Serialize_TPMI_DH_PERSISTENT(
|
|
persistent_handle,
|
|
&persistent_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(object_handle_name.data(),
|
|
object_handle_name.size());
|
|
handle_section_bytes += object_handle_bytes;
|
|
command_size += object_handle_bytes.size();
|
|
hash->Update(persistent_handle_bytes.data(),
|
|
persistent_handle_bytes.size());
|
|
parameter_section_bytes += persistent_handle_bytes;
|
|
command_size += persistent_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_EvictControl(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_EvictControl;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void EvictControlErrorCallback(
|
|
const Tpm::EvictControlResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void EvictControlResponseParser(
|
|
const Tpm::EvictControlResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EvictControlErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_EvictControl(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::EvictControl(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_PERSISTENT& persistent_handle,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const EvictControlResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(EvictControlErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(EvictControlResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EvictControl(
|
|
auth,
|
|
auth_name,
|
|
object_handle,
|
|
object_handle_name,
|
|
persistent_handle,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::EvictControlSync(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPMI_DH_OBJECT& object_handle,
|
|
const std::string& object_handle_name,
|
|
const TPMI_DH_PERSISTENT& persistent_handle,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_EvictControl(
|
|
auth,
|
|
auth_name,
|
|
object_handle,
|
|
object_handle_name,
|
|
persistent_handle,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_EvictControl(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ReadClock(
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ReadClock;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ReadClock(
|
|
const std::string& response,
|
|
TPMS_TIME_INFO* current_time,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ReadClock;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string current_time_bytes;
|
|
rc = Parse_TPMS_TIME_INFO(
|
|
&buffer,
|
|
current_time,
|
|
¤t_time_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ReadClockErrorCallback(
|
|
const Tpm::ReadClockResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMS_TIME_INFO());
|
|
}
|
|
|
|
void ReadClockResponseParser(
|
|
const Tpm::ReadClockResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ReadClockErrorCallback, callback);
|
|
TPMS_TIME_INFO current_time;
|
|
TPM_RC rc = Tpm::ParseResponse_ReadClock(
|
|
response,
|
|
¤t_time,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
current_time);
|
|
}
|
|
|
|
void Tpm::ReadClock(
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ReadClockResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ReadClockErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ReadClockResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ReadClock(
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ReadClockSync(
|
|
TPMS_TIME_INFO* current_time,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ReadClock(
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ReadClock(
|
|
response,
|
|
current_time,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ClockSet(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const UINT64& new_time,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ClockSet;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_time_bytes;
|
|
rc = Serialize_UINT64(
|
|
new_time,
|
|
&new_time_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(new_time_bytes.data(),
|
|
new_time_bytes.size());
|
|
parameter_section_bytes += new_time_bytes;
|
|
command_size += new_time_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ClockSet(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ClockSet;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ClockSetErrorCallback(
|
|
const Tpm::ClockSetResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ClockSetResponseParser(
|
|
const Tpm::ClockSetResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClockSetErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_ClockSet(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::ClockSet(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const UINT64& new_time,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ClockSetResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClockSetErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ClockSetResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClockSet(
|
|
auth,
|
|
auth_name,
|
|
new_time,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ClockSetSync(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const UINT64& new_time,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClockSet(
|
|
auth,
|
|
auth_name,
|
|
new_time,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ClockSet(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_ClockRateAdjust(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPM_CLOCK_ADJUST& rate_adjust,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_ClockRateAdjust;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string rate_adjust_bytes;
|
|
rc = Serialize_TPM_CLOCK_ADJUST(
|
|
rate_adjust,
|
|
&rate_adjust_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_name.data(),
|
|
auth_name.size());
|
|
handle_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(rate_adjust_bytes.data(),
|
|
rate_adjust_bytes.size());
|
|
parameter_section_bytes += rate_adjust_bytes;
|
|
command_size += rate_adjust_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_ClockRateAdjust(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_ClockRateAdjust;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void ClockRateAdjustErrorCallback(
|
|
const Tpm::ClockRateAdjustResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void ClockRateAdjustResponseParser(
|
|
const Tpm::ClockRateAdjustResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClockRateAdjustErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_ClockRateAdjust(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::ClockRateAdjust(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPM_CLOCK_ADJUST& rate_adjust,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const ClockRateAdjustResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(ClockRateAdjustErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(ClockRateAdjustResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClockRateAdjust(
|
|
auth,
|
|
auth_name,
|
|
rate_adjust,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::ClockRateAdjustSync(
|
|
const TPMI_RH_PROVISION& auth,
|
|
const std::string& auth_name,
|
|
const TPM_CLOCK_ADJUST& rate_adjust,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_ClockRateAdjust(
|
|
auth,
|
|
auth_name,
|
|
rate_adjust,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_ClockRateAdjust(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_GetCapability(
|
|
const TPM_CAP& capability,
|
|
const UINT32& property,
|
|
const UINT32& property_count,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_GetCapability;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string capability_bytes;
|
|
rc = Serialize_TPM_CAP(
|
|
capability,
|
|
&capability_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string property_bytes;
|
|
rc = Serialize_UINT32(
|
|
property,
|
|
&property_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string property_count_bytes;
|
|
rc = Serialize_UINT32(
|
|
property_count,
|
|
&property_count_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(capability_bytes.data(),
|
|
capability_bytes.size());
|
|
parameter_section_bytes += capability_bytes;
|
|
command_size += capability_bytes.size();
|
|
hash->Update(property_bytes.data(),
|
|
property_bytes.size());
|
|
parameter_section_bytes += property_bytes;
|
|
command_size += property_bytes.size();
|
|
hash->Update(property_count_bytes.data(),
|
|
property_count_bytes.size());
|
|
parameter_section_bytes += property_count_bytes;
|
|
command_size += property_count_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_GetCapability(
|
|
const std::string& response,
|
|
TPMI_YES_NO* more_data,
|
|
TPMS_CAPABILITY_DATA* capability_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_GetCapability;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string more_data_bytes;
|
|
rc = Parse_TPMI_YES_NO(
|
|
&buffer,
|
|
more_data,
|
|
&more_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string capability_data_bytes;
|
|
rc = Parse_TPMS_CAPABILITY_DATA(
|
|
&buffer,
|
|
capability_data,
|
|
&capability_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void GetCapabilityErrorCallback(
|
|
const Tpm::GetCapabilityResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPMI_YES_NO(),
|
|
TPMS_CAPABILITY_DATA());
|
|
}
|
|
|
|
void GetCapabilityResponseParser(
|
|
const Tpm::GetCapabilityResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetCapabilityErrorCallback, callback);
|
|
TPMI_YES_NO more_data;
|
|
TPMS_CAPABILITY_DATA capability_data;
|
|
TPM_RC rc = Tpm::ParseResponse_GetCapability(
|
|
response,
|
|
&more_data,
|
|
&capability_data,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
more_data,
|
|
capability_data);
|
|
}
|
|
|
|
void Tpm::GetCapability(
|
|
const TPM_CAP& capability,
|
|
const UINT32& property,
|
|
const UINT32& property_count,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const GetCapabilityResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(GetCapabilityErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(GetCapabilityResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetCapability(
|
|
capability,
|
|
property,
|
|
property_count,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::GetCapabilitySync(
|
|
const TPM_CAP& capability,
|
|
const UINT32& property,
|
|
const UINT32& property_count,
|
|
TPMI_YES_NO* more_data,
|
|
TPMS_CAPABILITY_DATA* capability_data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_GetCapability(
|
|
capability,
|
|
property,
|
|
property_count,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_GetCapability(
|
|
response,
|
|
more_data,
|
|
capability_data,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_TestParms(
|
|
const TPMT_PUBLIC_PARMS& parameters,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_TestParms;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string parameters_bytes;
|
|
rc = Serialize_TPMT_PUBLIC_PARMS(
|
|
parameters,
|
|
¶meters_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(parameters_bytes.data(),
|
|
parameters_bytes.size());
|
|
parameter_section_bytes += parameters_bytes;
|
|
command_size += parameters_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_TestParms(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_TestParms;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void TestParmsErrorCallback(
|
|
const Tpm::TestParmsResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void TestParmsResponseParser(
|
|
const Tpm::TestParmsResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(TestParmsErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_TestParms(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::TestParms(
|
|
const TPMT_PUBLIC_PARMS& parameters,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const TestParmsResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(TestParmsErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(TestParmsResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_TestParms(
|
|
parameters,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::TestParmsSync(
|
|
const TPMT_PUBLIC_PARMS& parameters,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_TestParms(
|
|
parameters,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_TestParms(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_DefineSpace(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPM2B_NV_PUBLIC& public_info,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_DefineSpace;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
auth,
|
|
&auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string public_info_bytes;
|
|
rc = Serialize_TPM2B_NV_PUBLIC(
|
|
public_info,
|
|
&public_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(auth_bytes.data(),
|
|
auth_bytes.size());
|
|
parameter_section_bytes += auth_bytes;
|
|
command_size += auth_bytes.size();
|
|
hash->Update(public_info_bytes.data(),
|
|
public_info_bytes.size());
|
|
parameter_section_bytes += public_info_bytes;
|
|
command_size += public_info_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_DefineSpace(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_DefineSpace;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_DefineSpaceErrorCallback(
|
|
const Tpm::NV_DefineSpaceResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_DefineSpaceResponseParser(
|
|
const Tpm::NV_DefineSpaceResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_DefineSpaceErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_DefineSpace(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_DefineSpace(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPM2B_NV_PUBLIC& public_info,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_DefineSpaceResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_DefineSpaceErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_DefineSpaceResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_DefineSpace(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
auth,
|
|
public_info,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_DefineSpaceSync(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPM2B_AUTH& auth,
|
|
const TPM2B_NV_PUBLIC& public_info,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_DefineSpace(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
auth,
|
|
public_info,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_DefineSpace(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_UndefineSpace(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_UndefineSpace;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_UndefineSpace(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_UndefineSpace;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_UndefineSpaceErrorCallback(
|
|
const Tpm::NV_UndefineSpaceResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_UndefineSpaceResponseParser(
|
|
const Tpm::NV_UndefineSpaceResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_UndefineSpaceErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_UndefineSpace(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_UndefineSpace(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_UndefineSpaceResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_UndefineSpaceErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_UndefineSpaceResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_UndefineSpace(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_UndefineSpaceSync(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_UndefineSpace(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_UndefineSpace(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_UndefineSpaceSpecial(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_RH_PLATFORM& platform,
|
|
const std::string& platform_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_UndefineSpaceSpecial;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string platform_bytes;
|
|
rc = Serialize_TPMI_RH_PLATFORM(
|
|
platform,
|
|
&platform_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(platform_name.data(),
|
|
platform_name.size());
|
|
handle_section_bytes += platform_bytes;
|
|
command_size += platform_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_UndefineSpaceSpecial(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_UndefineSpaceSpecial;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_UndefineSpaceSpecialErrorCallback(
|
|
const Tpm::NV_UndefineSpaceSpecialResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_UndefineSpaceSpecialResponseParser(
|
|
const Tpm::NV_UndefineSpaceSpecialResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_UndefineSpaceSpecialErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_UndefineSpaceSpecial(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_UndefineSpaceSpecial(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_RH_PLATFORM& platform,
|
|
const std::string& platform_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_UndefineSpaceSpecialResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_UndefineSpaceSpecialErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_UndefineSpaceSpecialResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_UndefineSpaceSpecial(
|
|
nv_index,
|
|
nv_index_name,
|
|
platform,
|
|
platform_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_UndefineSpaceSpecialSync(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPMI_RH_PLATFORM& platform,
|
|
const std::string& platform_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_UndefineSpaceSpecial(
|
|
nv_index,
|
|
nv_index_name,
|
|
platform,
|
|
platform_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_UndefineSpaceSpecial(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_ReadPublic(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_ReadPublic;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_ReadPublic(
|
|
const std::string& response,
|
|
TPM2B_NV_PUBLIC* nv_public,
|
|
TPM2B_NAME* nv_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_ReadPublic;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string nv_public_bytes;
|
|
rc = Parse_TPM2B_NV_PUBLIC(
|
|
&buffer,
|
|
nv_public,
|
|
&nv_public_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_name_bytes;
|
|
rc = Parse_TPM2B_NAME(
|
|
&buffer,
|
|
nv_name,
|
|
&nv_name_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = nv_public_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
nv_public_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_NV_PUBLIC(
|
|
&nv_public_bytes,
|
|
nv_public,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_ReadPublicErrorCallback(
|
|
const Tpm::NV_ReadPublicResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_NV_PUBLIC(),
|
|
TPM2B_NAME());
|
|
}
|
|
|
|
void NV_ReadPublicResponseParser(
|
|
const Tpm::NV_ReadPublicResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadPublicErrorCallback, callback);
|
|
TPM2B_NV_PUBLIC nv_public;
|
|
TPM2B_NAME nv_name;
|
|
TPM_RC rc = Tpm::ParseResponse_NV_ReadPublic(
|
|
response,
|
|
&nv_public,
|
|
&nv_name,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
nv_public,
|
|
nv_name);
|
|
}
|
|
|
|
void Tpm::NV_ReadPublic(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_ReadPublicResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadPublicErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_ReadPublicResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ReadPublic(
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_ReadPublicSync(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
TPM2B_NV_PUBLIC* nv_public,
|
|
TPM2B_NAME* nv_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ReadPublic(
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_ReadPublic(
|
|
response,
|
|
nv_public,
|
|
nv_name,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_Write(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
const UINT16& offset,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_Write;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string data_bytes;
|
|
rc = Serialize_TPM2B_MAX_NV_BUFFER(
|
|
data,
|
|
&data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string offset_bytes;
|
|
rc = Serialize_UINT16(
|
|
offset,
|
|
&offset_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(data_bytes.data(),
|
|
data_bytes.size());
|
|
parameter_section_bytes += data_bytes;
|
|
command_size += data_bytes.size();
|
|
hash->Update(offset_bytes.data(),
|
|
offset_bytes.size());
|
|
parameter_section_bytes += offset_bytes;
|
|
command_size += offset_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_Write(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_Write;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_WriteErrorCallback(
|
|
const Tpm::NV_WriteResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_WriteResponseParser(
|
|
const Tpm::NV_WriteResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_WriteErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_Write(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_Write(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
const UINT16& offset,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_WriteResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_WriteErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_WriteResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Write(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
data,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_WriteSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
const UINT16& offset,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Write(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
data,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_Write(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_Increment(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_Increment;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_Increment(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_Increment;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_IncrementErrorCallback(
|
|
const Tpm::NV_IncrementResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_IncrementResponseParser(
|
|
const Tpm::NV_IncrementResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_IncrementErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_Increment(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_Increment(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_IncrementResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_IncrementErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_IncrementResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Increment(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_IncrementSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Increment(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_Increment(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_Extend(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_Extend;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string data_bytes;
|
|
rc = Serialize_TPM2B_MAX_NV_BUFFER(
|
|
data,
|
|
&data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(data_bytes.data(),
|
|
data_bytes.size());
|
|
parameter_section_bytes += data_bytes;
|
|
command_size += data_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_Extend(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_Extend;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_ExtendErrorCallback(
|
|
const Tpm::NV_ExtendResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_ExtendResponseParser(
|
|
const Tpm::NV_ExtendResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ExtendErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_Extend(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_Extend(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_ExtendResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ExtendErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_ExtendResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Extend(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_ExtendSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_MAX_NV_BUFFER& data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Extend(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
data,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_Extend(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_SetBits(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT64& bits,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_SetBits;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string bits_bytes;
|
|
rc = Serialize_UINT64(
|
|
bits,
|
|
&bits_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(bits_bytes.data(),
|
|
bits_bytes.size());
|
|
parameter_section_bytes += bits_bytes;
|
|
command_size += bits_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_SetBits(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_SetBits;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_SetBitsErrorCallback(
|
|
const Tpm::NV_SetBitsResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_SetBitsResponseParser(
|
|
const Tpm::NV_SetBitsResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_SetBitsErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_SetBits(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_SetBits(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT64& bits,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_SetBitsResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_SetBitsErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_SetBitsResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_SetBits(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
bits,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_SetBitsSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT64& bits,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_SetBits(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
bits,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_SetBits(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_WriteLock(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_WriteLock;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_WriteLock(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_WriteLock;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_WriteLockErrorCallback(
|
|
const Tpm::NV_WriteLockResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_WriteLockResponseParser(
|
|
const Tpm::NV_WriteLockResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_WriteLockErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_WriteLock(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_WriteLock(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_WriteLockResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_WriteLockErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_WriteLockResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_WriteLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_WriteLockSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_WriteLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_WriteLock(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_GlobalWriteLock(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_GlobalWriteLock;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_PROVISION(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_GlobalWriteLock(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_GlobalWriteLock;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_GlobalWriteLockErrorCallback(
|
|
const Tpm::NV_GlobalWriteLockResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_GlobalWriteLockResponseParser(
|
|
const Tpm::NV_GlobalWriteLockResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_GlobalWriteLockErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_GlobalWriteLock(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_GlobalWriteLock(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_GlobalWriteLockResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_GlobalWriteLockErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_GlobalWriteLockResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_GlobalWriteLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_GlobalWriteLockSync(
|
|
const TPMI_RH_PROVISION& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_GlobalWriteLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_GlobalWriteLock(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_Read(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_Read;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string size_bytes;
|
|
rc = Serialize_UINT16(
|
|
size,
|
|
&size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string offset_bytes;
|
|
rc = Serialize_UINT16(
|
|
offset,
|
|
&offset_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(size_bytes.data(),
|
|
size_bytes.size());
|
|
parameter_section_bytes += size_bytes;
|
|
command_size += size_bytes.size();
|
|
hash->Update(offset_bytes.data(),
|
|
offset_bytes.size());
|
|
parameter_section_bytes += offset_bytes;
|
|
command_size += offset_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_Read(
|
|
const std::string& response,
|
|
TPM2B_MAX_NV_BUFFER* data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_Read;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string data_bytes;
|
|
rc = Parse_TPM2B_MAX_NV_BUFFER(
|
|
&buffer,
|
|
data,
|
|
&data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = data_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
data_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_MAX_NV_BUFFER(
|
|
&data_bytes,
|
|
data,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_ReadErrorCallback(
|
|
const Tpm::NV_ReadResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_MAX_NV_BUFFER());
|
|
}
|
|
|
|
void NV_ReadResponseParser(
|
|
const Tpm::NV_ReadResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadErrorCallback, callback);
|
|
TPM2B_MAX_NV_BUFFER data;
|
|
TPM_RC rc = Tpm::ParseResponse_NV_Read(
|
|
response,
|
|
&data,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
data);
|
|
}
|
|
|
|
void Tpm::NV_Read(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_ReadResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_ReadResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Read(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
size,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_ReadSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
TPM2B_MAX_NV_BUFFER* data,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Read(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
size,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_Read(
|
|
response,
|
|
data,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_ReadLock(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_ReadLock;
|
|
bool is_command_parameter_encryption_possible = false;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_ReadLock(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_ReadLock;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_ReadLockErrorCallback(
|
|
const Tpm::NV_ReadLockResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_ReadLockResponseParser(
|
|
const Tpm::NV_ReadLockResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadLockErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_ReadLock(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_ReadLock(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_ReadLockResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ReadLockErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_ReadLockResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ReadLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_ReadLockSync(
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ReadLock(
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_ReadLock(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_ChangeAuth(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_ChangeAuth;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = false;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string new_auth_bytes;
|
|
rc = Serialize_TPM2B_AUTH(
|
|
new_auth,
|
|
&new_auth_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = new_auth_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
new_auth_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(new_auth_bytes.data(),
|
|
new_auth_bytes.size());
|
|
parameter_section_bytes += new_auth_bytes;
|
|
command_size += new_auth_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_ChangeAuth(
|
|
const std::string& response,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_ChangeAuth;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_ChangeAuthErrorCallback(
|
|
const Tpm::NV_ChangeAuthResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code);
|
|
}
|
|
|
|
void NV_ChangeAuthResponseParser(
|
|
const Tpm::NV_ChangeAuthResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ChangeAuthErrorCallback, callback);
|
|
TPM_RC rc = Tpm::ParseResponse_NV_ChangeAuth(
|
|
response,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc);
|
|
}
|
|
|
|
void Tpm::NV_ChangeAuth(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_ChangeAuthResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_ChangeAuthErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_ChangeAuthResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ChangeAuth(
|
|
nv_index,
|
|
nv_index_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_ChangeAuthSync(
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_AUTH& new_auth,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_ChangeAuth(
|
|
nv_index,
|
|
nv_index_name,
|
|
new_auth,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_ChangeAuth(
|
|
response,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
TPM_RC Tpm::SerializeCommand_NV_Certify(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
std::string* serialized_command,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
|
|
UINT32 command_size = 10; // Header size.
|
|
std::string handle_section_bytes;
|
|
std::string parameter_section_bytes;
|
|
TPM_CC command_code = TPM_CC_NV_Certify;
|
|
bool is_command_parameter_encryption_possible = true;
|
|
bool is_response_parameter_encryption_possible = true;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string sign_handle_bytes;
|
|
rc = Serialize_TPMI_DH_OBJECT(
|
|
sign_handle,
|
|
&sign_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string auth_handle_bytes;
|
|
rc = Serialize_TPMI_RH_NV_AUTH(
|
|
auth_handle,
|
|
&auth_handle_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string nv_index_bytes;
|
|
rc = Serialize_TPMI_RH_NV_INDEX(
|
|
nv_index,
|
|
&nv_index_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string qualifying_data_bytes;
|
|
rc = Serialize_TPM2B_DATA(
|
|
qualifying_data,
|
|
&qualifying_data_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string in_scheme_bytes;
|
|
rc = Serialize_TPMT_SIG_SCHEME(
|
|
in_scheme,
|
|
&in_scheme_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string size_bytes;
|
|
rc = Serialize_UINT16(
|
|
size,
|
|
&size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string offset_bytes;
|
|
rc = Serialize_UINT16(
|
|
offset,
|
|
&offset_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (authorization_delegate) {
|
|
// Encrypt just the parameter data, not the size.
|
|
std::string tmp = qualifying_data_bytes.substr(2);
|
|
if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
qualifying_data_bytes.replace(2, std::string::npos, tmp);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(sign_handle_name.data(),
|
|
sign_handle_name.size());
|
|
handle_section_bytes += sign_handle_bytes;
|
|
command_size += sign_handle_bytes.size();
|
|
hash->Update(auth_handle_name.data(),
|
|
auth_handle_name.size());
|
|
handle_section_bytes += auth_handle_bytes;
|
|
command_size += auth_handle_bytes.size();
|
|
hash->Update(nv_index_name.data(),
|
|
nv_index_name.size());
|
|
handle_section_bytes += nv_index_bytes;
|
|
command_size += nv_index_bytes.size();
|
|
hash->Update(qualifying_data_bytes.data(),
|
|
qualifying_data_bytes.size());
|
|
parameter_section_bytes += qualifying_data_bytes;
|
|
command_size += qualifying_data_bytes.size();
|
|
hash->Update(in_scheme_bytes.data(),
|
|
in_scheme_bytes.size());
|
|
parameter_section_bytes += in_scheme_bytes;
|
|
command_size += in_scheme_bytes.size();
|
|
hash->Update(size_bytes.data(),
|
|
size_bytes.size());
|
|
parameter_section_bytes += size_bytes;
|
|
command_size += size_bytes.size();
|
|
hash->Update(offset_bytes.data(),
|
|
offset_bytes.size());
|
|
parameter_section_bytes += offset_bytes;
|
|
command_size += offset_bytes.size();
|
|
std::string command_hash(32, 0);
|
|
hash->Finish(string_as_array(&command_hash), command_hash.size());
|
|
std::string authorization_section_bytes;
|
|
std::string authorization_size_bytes;
|
|
if (authorization_delegate) {
|
|
if (!authorization_delegate->GetCommandAuthorization(
|
|
command_hash,
|
|
is_command_parameter_encryption_possible,
|
|
is_response_parameter_encryption_possible,
|
|
&authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
if (!authorization_section_bytes.empty()) {
|
|
tag = TPM_ST_SESSIONS;
|
|
std::string tmp;
|
|
rc = Serialize_UINT32(authorization_section_bytes.size(),
|
|
&authorization_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
command_size += authorization_size_bytes.size() +
|
|
authorization_section_bytes.size();
|
|
}
|
|
}
|
|
std::string tag_bytes;
|
|
rc = Serialize_TPMI_ST_COMMAND_TAG(
|
|
tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string command_size_bytes;
|
|
rc = Serialize_UINT32(
|
|
command_size,
|
|
&command_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
*serialized_command = tag_bytes +
|
|
command_size_bytes +
|
|
command_code_bytes +
|
|
handle_section_bytes +
|
|
authorization_size_bytes +
|
|
authorization_section_bytes +
|
|
parameter_section_bytes;
|
|
CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
|
|
VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
|
|
serialized_command->size());
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
TPM_RC Tpm::ParseResponse_NV_Certify(
|
|
const std::string& response,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(3) << __func__;
|
|
VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
|
|
TPM_RC rc = TPM_RC_SUCCESS;
|
|
std::string buffer(response);
|
|
TPM_ST tag;
|
|
std::string tag_bytes;
|
|
rc = Parse_TPM_ST(
|
|
&buffer,
|
|
&tag,
|
|
&tag_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
UINT32 response_size;
|
|
std::string response_size_bytes;
|
|
rc = Parse_UINT32(
|
|
&buffer,
|
|
&response_size,
|
|
&response_size_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
TPM_RC response_code;
|
|
std::string response_code_bytes;
|
|
rc = Parse_TPM_RC(
|
|
&buffer,
|
|
&response_code,
|
|
&response_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (response_size != response.size()) {
|
|
return TPM_RC_SIZE;
|
|
}
|
|
if (response_code != TPM_RC_SUCCESS) {
|
|
return response_code;
|
|
}
|
|
TPM_CC command_code = TPM_CC_NV_Certify;
|
|
std::string command_code_bytes;
|
|
rc = Serialize_TPM_CC(
|
|
command_code,
|
|
&command_code_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string authorization_section_bytes;
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32 parameter_section_size = buffer.size();
|
|
rc = Parse_UINT32(&buffer, ¶meter_section_size, nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (parameter_section_size > buffer.size()) {
|
|
return TPM_RC_INSUFFICIENT;
|
|
}
|
|
authorization_section_bytes = buffer.substr(parameter_section_size);
|
|
// Keep the parameter section in |buffer|.
|
|
buffer.erase(parameter_section_size);
|
|
}
|
|
scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
|
|
crypto::SecureHash::SHA256));
|
|
hash->Update(response_code_bytes.data(),
|
|
response_code_bytes.size());
|
|
hash->Update(command_code_bytes.data(),
|
|
command_code_bytes.size());
|
|
hash->Update(buffer.data(),
|
|
buffer.size());
|
|
std::string response_hash(32, 0);
|
|
hash->Finish(string_as_array(&response_hash), response_hash.size());
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
if (!authorization_delegate->CheckResponseAuthorization(
|
|
response_hash,
|
|
authorization_section_bytes)) {
|
|
return TRUNKS_RC_AUTHORIZATION_FAILED;
|
|
}
|
|
}
|
|
std::string certify_info_bytes;
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&buffer,
|
|
certify_info,
|
|
&certify_info_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string signature_bytes;
|
|
rc = Parse_TPMT_SIGNATURE(
|
|
&buffer,
|
|
signature,
|
|
&signature_bytes);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
CHECK(authorization_delegate) << "Authorization delegate missing!";
|
|
// Decrypt just the parameter data, not the size.
|
|
std::string tmp = certify_info_bytes.substr(2);
|
|
if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
|
|
return TRUNKS_RC_ENCRYPTION_FAILED;
|
|
}
|
|
certify_info_bytes.replace(2, std::string::npos, tmp);
|
|
rc = Parse_TPM2B_ATTEST(
|
|
&certify_info_bytes,
|
|
certify_info,
|
|
nullptr);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
void NV_CertifyErrorCallback(
|
|
const Tpm::NV_CertifyResponse& callback,
|
|
TPM_RC response_code) {
|
|
VLOG(1) << __func__;
|
|
callback.Run(response_code,
|
|
TPM2B_ATTEST(),
|
|
TPMT_SIGNATURE());
|
|
}
|
|
|
|
void NV_CertifyResponseParser(
|
|
const Tpm::NV_CertifyResponse& callback,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const std::string& response) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_CertifyErrorCallback, callback);
|
|
TPM2B_ATTEST certify_info;
|
|
TPMT_SIGNATURE signature;
|
|
TPM_RC rc = Tpm::ParseResponse_NV_Certify(
|
|
response,
|
|
&certify_info,
|
|
&signature,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
callback.Run(
|
|
rc,
|
|
certify_info,
|
|
signature);
|
|
}
|
|
|
|
void Tpm::NV_Certify(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
AuthorizationDelegate* authorization_delegate,
|
|
const NV_CertifyResponse& callback) {
|
|
VLOG(1) << __func__;
|
|
base::Callback<void(TPM_RC)> error_reporter =
|
|
base::Bind(NV_CertifyErrorCallback, callback);
|
|
base::Callback<void(const std::string&)> parser =
|
|
base::Bind(NV_CertifyResponseParser,
|
|
callback,
|
|
authorization_delegate);
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Certify(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
size,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
error_reporter.Run(rc);
|
|
return;
|
|
}
|
|
transceiver_->SendCommand(command, parser);
|
|
}
|
|
|
|
TPM_RC Tpm::NV_CertifySync(
|
|
const TPMI_DH_OBJECT& sign_handle,
|
|
const std::string& sign_handle_name,
|
|
const TPMI_RH_NV_AUTH& auth_handle,
|
|
const std::string& auth_handle_name,
|
|
const TPMI_RH_NV_INDEX& nv_index,
|
|
const std::string& nv_index_name,
|
|
const TPM2B_DATA& qualifying_data,
|
|
const TPMT_SIG_SCHEME& in_scheme,
|
|
const UINT16& size,
|
|
const UINT16& offset,
|
|
TPM2B_ATTEST* certify_info,
|
|
TPMT_SIGNATURE* signature,
|
|
AuthorizationDelegate* authorization_delegate) {
|
|
VLOG(1) << __func__;
|
|
std::string command;
|
|
TPM_RC rc = SerializeCommand_NV_Certify(
|
|
sign_handle,
|
|
sign_handle_name,
|
|
auth_handle,
|
|
auth_handle_name,
|
|
nv_index,
|
|
nv_index_name,
|
|
qualifying_data,
|
|
in_scheme,
|
|
size,
|
|
offset,
|
|
&command,
|
|
authorization_delegate);
|
|
if (rc != TPM_RC_SUCCESS) {
|
|
return rc;
|
|
}
|
|
std::string response = transceiver_->SendCommandAndWait(command);
|
|
rc = ParseResponse_NV_Certify(
|
|
response,
|
|
certify_info,
|
|
signature,
|
|
authorization_delegate);
|
|
return rc;
|
|
}
|
|
|
|
} // namespace trunks
|