void TestUtil::SealSeedToEk()

in client-library/src/Attestation/LinuxTpm/testclient/TestUtil.cpp [68:217]


void TestUtil::SealSeedToEk(
    Tss2Ctx& ctx,
    attest::PcrSet& pcrSet,
    attest::HashAlg hashAlg,
    std::vector<unsigned char>& clearKey,
    std::vector<unsigned char>& outPub,
    std::vector<unsigned char>& outPriv,
    std::vector<unsigned char>& encryptedSeed,
    bool useStoredEk)
{
    TSS2_RC ret;
    unique_esys_tr parent(ctx.Get());
    if (useStoredEk)
    {
        parent = std::move(Tss2Util::HandleToEsys(ctx, EK_PUB_INDEX));
    }
    else
    {
        TPM2B_PUBLIC* outPublic = NULL;
        ESYS_TR ekHandle = Tss2Util::GenerateEkFromSpec(ctx, false, &outPublic);
        // Store the object in a unique_c_ptr<> to manage clean up after use.
        unique_c_ptr<TPM2B_PUBLIC> outPubPtr(outPublic);

        unique_esys_tr ek(ekHandle, ctx.Get());
        parent = std::move(ek);
    }

    TPM2B_PUBLIC inPub = {0};
    inPub.publicArea.type = TPM2_ALG_KEYEDHASH;
    inPub.publicArea.nameAlg = TPM2_ALG_SHA256;
    inPub.publicArea.objectAttributes = TPMA_OBJECT_USERWITHAUTH;
    inPub.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL;

    TPM2B_DATA outsideInfo = {0};
    auto creationPcr = Tss2Util::GetTssPcrSelection(ctx, pcrSet, hashAlg);

    TPM2B_SENSITIVE_CREATE inSensitive = {0};
    inSensitive.sensitive.data.size = static_cast<uint16_t>(clearKey.size());
    memcpy(inSensitive.sensitive.data.buffer, clearKey.data(), clearKey.size());

    TPM2B_PRIVATE* outPrivTmp;
    TPM2B_PUBLIC* outPubTmp;

    //
    // Create a policy that such that the created object can be duplicated and set
    // that as the authValue for inPub
    //

    Tss2Session session(ctx.Get());
    session.Start(TPM2_SE_TRIAL);
    session.PolicyCommandCode(TPM2_CC_Duplicate);

    auto policyDigest = session.GetDigest();
    inPub.publicArea.authPolicy = *policyDigest;

    session.Restart(TPM2_SE_POLICY);
    session.PolicySecret(ESYS_TR_RH_ENDORSEMENT);

    //
    // Create object
    // 
    ret = Esys_Create(ctx.Get(), parent.get(),
                session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
                &inSensitive, &inPub, &outsideInfo, creationPcr.get(),
                &outPrivTmp, &outPubTmp, nullptr, nullptr, nullptr);
    if (ret != TSS2_RC_SUCCESS)
    {
        throw Tss2Exception("Failed to create", ret);
    }

    unique_c_ptr<TPM2B_PUBLIC> outPubUnique(outPubTmp);
    unique_c_ptr<TPM2B_PRIVATE> outPrivUnique(outPrivTmp);

    //
    // Load created object so we can duplicate it
    //
    session.Restart(TPM2_SE_POLICY);
    session.PolicySecret(ESYS_TR_RH_ENDORSEMENT);
    
    unique_esys_tr loadedData(ctx.Get());
    ret = Esys_Load(ctx.Get(), parent.get(),
            session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
            outPrivUnique.get(), outPubUnique.get(), loadedData.get_ptr());
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to load encrypted data", ret);
    }

    //
    // Duplicate private so it can be imported by unseal
    // 
    session.Restart(TPM2_SE_POLICY);
    session.PolicyCommandCode(TPM2_CC_Duplicate);

    TPMT_SYM_DEF_OBJECT symDef = { TPM2_ALG_NULL, 0, TPM2_ALG_NULL };
    TPM2B_DATA* innerKey;
    TPM2B_PRIVATE* duplicate;
    TPM2B_ENCRYPTED_SECRET* outSymSeed;

    ret = Esys_Duplicate(ctx.Get(), loadedData.get(), parent.get(),
            session.GetHandle(), ESYS_TR_NONE, ESYS_TR_NONE,
            nullptr, &symDef, &innerKey, &duplicate, &outSymSeed);
    if (ret != TSS2_RC_SUCCESS)
    {
        throw Tss2Exception("Esys_Duplicate", ret);
    }

    unique_c_ptr<TPM2B_DATA> innerKeyUnique(innerKey);
    unique_c_ptr<TPM2B_PRIVATE> duplicateUnique(duplicate);
    unique_c_ptr<TPM2B_ENCRYPTED_SECRET> outSymSeedUnique(outSymSeed);

    //
    // Serialize all outputs
    //

    // Serialize outPub
    size_t offset = 0;
    outPub.resize(sizeof(*outPubUnique));
    ret = Tss2_MU_TPM2B_PUBLIC_Marshal(outPubUnique.get(),
            outPub.data(),
            outPub.size(),
            &offset);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to marshal TPM2B_PUBLIC", ret);
    }
    outPub.resize(offset);

    // Serialize outPriv
    offset = 0;
    outPriv.resize(sizeof(*duplicateUnique));
    ret = Tss2_MU_TPM2B_PRIVATE_Marshal(duplicateUnique.get(),
            outPriv.data(),
            outPriv.size(),
            &offset);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to marshal TPM2B_PRIVATE", ret);
    }
    outPriv.resize(offset);

    // Serialize outSymSeed
    offset = 0;
    encryptedSeed.resize(sizeof(*outSymSeedUnique));
    ret = Tss2_MU_TPM2B_ENCRYPTED_SECRET_Marshal(outSymSeedUnique.get(),
            encryptedSeed.data(),
            encryptedSeed.size(),
            &offset);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to marshal TPM2B_ENCRYPTED_SECRET", ret);
    }
    encryptedSeed.resize(offset);
}