std::vector Tss2Wrapper::UnsealInternal()

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);
}