attest::PcrQuote Tss2Wrapper::GetPCRQuote()

in client-library/src/Attestation/LinuxTpm/lib/Tss2Wrapper.cpp [133:212]


attest::PcrQuote Tss2Wrapper::GetPCRQuote(
    const attest::PcrList& pcrs, attest::HashAlg hashAlg)
{
    TSS2_RC ret;
    unique_c_ptr<TPM2B_ATTEST> quotePtr;
    unique_c_ptr<TPMT_SIGNATURE> sigPtr;

    attest::PcrSet pcrSet;
    pcrSet.hashAlg = hashAlg;
    // Select PCRs provided by input vector
    for (auto& pcr : pcrs) {
        attest::PcrValue pcrVal;
        pcrVal.index = pcr;
        pcrSet.pcrs.push_back(pcrVal);
    }

    auto signHandle = Tss2Util::HandleToEsys(*ctx, AIK_PUB_INDEX);
    auto pcrSelect = Tss2Util::GetTssPcrSelection(*ctx, pcrSet, hashAlg);

    TPM2B_DATA inData = {0};
    TPMT_SIG_SCHEME inScheme;
    inScheme.scheme = TPM2_ALG_NULL;
    TPM2B_ATTEST *outQuote;
    TPMT_SIGNATURE *outSig;

    ret = Esys_Quote(this->ctx->Get(),
                        signHandle.get(),
                        ESYS_TR_PASSWORD,
                        ESYS_TR_NONE,
                        ESYS_TR_NONE,
                        &inData,
                        &inScheme,
                        pcrSelect.get(),
                        &outQuote,
                        &outSig);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to quote PCRs", ret);
    }

    quotePtr = unique_c_ptr<TPM2B_ATTEST>(outQuote);
    sigPtr = unique_c_ptr<TPMT_SIGNATURE>(outSig);

    if (quotePtr == nullptr || sigPtr == nullptr)
    {
        // Unlikely to be null but better safe than segfault
        throw std::runtime_error("Failed to quote PCRs");
    }

    size_t offset;

    // Serialize TPM2B_ATTEST
    std::vector<unsigned char> quote(sizeof(*quotePtr));
    offset = 0; // in: index to start copying to, out: end of data

    ret = Tss2_MU_TPM2B_ATTEST_Marshal(quotePtr.get(), quote.data(), quote.size(), &offset);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to marshal TPMT_SIGNATURE", ret);
    }

    // Shrink to fit
    quote.resize(offset);

    // Serialize TPMT_SIGNATURE
    std::vector<unsigned char> signature(sizeof(*sigPtr));
    offset = 0; // in: index to start copying to, out: end of data

    ret = Tss2_MU_TPMT_SIGNATURE_Marshal(sigPtr.get(), signature.data(), signature.size(), &offset);
    if (ret != TSS2_RC_SUCCESS) {
        throw Tss2Exception("Failed to marshal TPMT_SIGNATURE", ret);
    }

    // Shrink to fit
    signature.resize(offset);

    attest::PcrQuote pcrQuote;
    pcrQuote.quote = quote;
    pcrQuote.signature = signature;

    return pcrQuote;
}