in client-library/src/Attestation/LinuxTpm/lib/Tss2Wrapper.cpp [391:504]
std::vector<unsigned char> Tss2Wrapper::UnsealInternal(
ESYS_TR keyHandle,
const std::vector<unsigned char>& importablePublic,
const std::vector<unsigned char>& importablePrivate,
const std::vector<unsigned char>& encryptedSeed,
const attest::PcrSet& pcrSet,
const attest::HashAlg hashAlg,
bool usePcrAuth)
{
TPM2B_PUBLIC inPub = { 0 };
TPM2B_PRIVATE inPriv = { 0 };
TPM2B_ENCRYPTED_SECRET seed = { 0 };
TSS2_RC ret;
// Unmarshal inPub
size_t offset = 0;
ret = Tss2_MU_TPM2B_PUBLIC_Unmarshal(importablePublic.data(),
importablePublic.size(), &offset, &inPub);
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to unmarshal TPM2B_PUBLIC", ret);
}
// Unmarshal inPriv
offset = 0;
ret = Tss2_MU_TPM2B_PRIVATE_Unmarshal(importablePrivate.data(), importablePrivate.size(),
&offset, &inPriv);
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to unmarshal TPM2B_PRIVATE", ret);
}
// Unmarshal seed
offset = 0;
ret = Tss2_MU_TPM2B_ENCRYPTED_SECRET_Unmarshal(encryptedSeed.data(), encryptedSeed.size(),
&offset, &seed);
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to unmarshal TPM2B_ENCRYPTED_SECRET", ret);
}
// Note: Sessions are reset between each call to clear policies from
// the session. This allows new policies to be set on the next call.
//
// Import symmetric key seeded by encryptedSeed
//
Tss2Session session(this->ctx->Get());
session.Start(TPM2_SE_POLICY);
session.PolicySecret(ESYS_TR_RH_ENDORSEMENT);
unique_c_ptr<TPM2B_PRIVATE> outPriv;
TPM2B_PRIVATE* tmpPriv;
TPMT_SYM_DEF_OBJECT symAlg;
symAlg.algorithm = TPM2_ALG_NULL;
ret = Esys_Import(this->ctx->Get(), keyHandle,
session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
nullptr, &inPub, &inPriv, &seed, &symAlg, &tmpPriv);
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to import encrypted data", ret);
}
outPriv.reset(tmpPriv);
//
// Load imported key
//
session.Restart(TPM2_SE_POLICY);
session.PolicySecret(ESYS_TR_RH_ENDORSEMENT);
unique_esys_tr loadedData(this->ctx->Get());
ret = Esys_Load(this->ctx->Get(), keyHandle,
session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
outPriv.get(), &inPub, loadedData.get_ptr());
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to load encrypted data", ret);
}
//
// Set PCR Policy
//
ESYS_TR authSession;
if (usePcrAuth)
{
// If the object was sealed to the PCR state, use the current PCR state to unseal
// it
auto pcrDigest = Tss2Util::GeneratePcrDigest(pcrSet, hashAlg);
// Pass PCR hash algorithm for TPML_PCR_SELECTION generation
auto pcrSelection = Tss2Util::GetTssPcrSelection(*ctx, pcrSet, pcrSet.hashAlg);
session.Restart(TPM2_SE_POLICY);
session.PolicyPcr(*pcrDigest, *pcrSelection);
authSession = session.GetHandle();
}
else
{
// This is primarily to unseal an object created by the integration tests.
// An object created with WITH_USERAUTH can be unsealed with a password.
// This needs to be done in tests due to complications with the authPolicy
// value on duplicated objects.
authSession = ESYS_TR_PASSWORD;
}
//
// Unseal loaded data
//
unique_c_ptr<TPM2B_SENSITIVE_DATA> outData;
TPM2B_SENSITIVE_DATA* outTmp;
ret = Esys_Unseal(this->ctx->Get(), loadedData.get(),
authSession, ESYS_TR_NONE, ESYS_TR_NONE,
&outTmp);
if (ret != TSS2_RC_SUCCESS) {
throw Tss2Exception("Failed to Unseal encrypted data", ret);
}
outData.reset(outTmp);
return std::vector<unsigned char>(outData->buffer, outData->buffer + outData->size);
}