TPM_RC TPM2X_BuildPolicy()

in lsvmutils/tpm2.c [4381:4524]


TPM_RC TPM2X_BuildPolicy(
    EFI_TCG2_PROTOCOL *protocol,
    TPMI_SH_AUTH_SESSION policySession,
    BOOLEAN predictive,
    UINT32 pcrMask,
    const SHA256Hash pcrs[MAX_PCRS],
    TPMI_ALG_HASH hashAlg,
    Error* err)
{
    TPM_RC rc;
    TPML_PCR_SELECTION pcrSelectionIn;
    UINT32 pcrUpdateCounter;
    TPML_PCR_SELECTION pcrSelectionOut;
    TPML_DIGEST pcrValues;
    UINT32 i = 0;
    UINT32 npcrs = 0;

    ClearErr(err);

    /* Check the hashing algorithm, should be SHA1 or SHA256. */
    if (hashAlg != TPM_ALG_SHA1 && hashAlg != TPM_ALG_SHA256)
    {
        SetErr(err, TCS("Unsupported hash function"));
        return TPM_RC_FAILURE;
    }


    /* Set NULL password for this policy */
    if ((rc = TPM2_PolicyPassword(
        protocol, 
        policySession,
        NULL, 
        NULL)) != TPM_RC_SUCCESS)
    {
        SetErr(err, TCS("failed to set the policy password"));
        return rc;
    }

    Memset(&pcrSelectionIn, 0, sizeof(pcrSelectionIn));
    pcrSelectionIn.count = 1;
    /* Note: this is not the number of PCRs */
    pcrSelectionIn.pcrSelections[0].sizeofSelect = 3;
    pcrSelectionIn.pcrSelections[0].hash = hashAlg;

    for (i = 0; i < MAX_PCRS; i++)
    {
        if (pcrMask & (1 << i))
        {
            TPMS_PCR_SELECTION_SelectPCR(&pcrSelectionIn.pcrSelections[0], i);
            npcrs++;
        }
    }

    Memset(&pcrUpdateCounter, 0, sizeof(pcrUpdateCounter));
    Memset(&pcrSelectionOut, 0, sizeof(pcrSelectionOut));
    Memset(&pcrValues, 0, sizeof(pcrValues));

    if (predictive)
    {
        UINT32 n;

        pcrValues.count = npcrs;

        for (i = 0, n = 0; i < MAX_PCRS; i++)
        {
            if (pcrMask & (1 << i))
            {
                Memcpy(pcrValues.digests[n].buffer, &pcrs[i], sizeof(pcrs[i]));
                pcrValues.digests[n].size = sizeof(pcrs[i]);
                n++;
            }
        }
    }
    else
    {
        if ((rc = TPM2_PCR_Read(
            protocol,
            NULL, /* input */
            &pcrSelectionIn, /* input */
            &pcrUpdateCounter, /* not used */
            &pcrSelectionOut, /* not used */
            &pcrValues,
            NULL)) != TPM_RC_SUCCESS)
        {
            SetErr(err, TCS("failed to read PCRs when building policy"));
            return rc;
        }
    }

    if (pcrValues.count != npcrs)
    {
        SetErr(err, TCS("unexpected error when building policy"));
        return TPM_RC_FAILURE;
    }

    /* Hash the PCRs together */
    TPM2B_DIGEST pcrDigest;
    {
        unsigned char data[sizeof(pcrValues.digests[0].buffer) * MAX_PCRS];
        unsigned char* end = data;

        Memset(&pcrDigest, 0, sizeof(pcrDigest));

        for (i = 0; i < npcrs; i++)
        {
            Memcpy(end, pcrValues.digests[i].buffer, pcrValues.digests[i].size);
            end += pcrValues.digests[i].size;
        }

        if (hashAlg == TPM_ALG_SHA1)
        {
            if (!ComputeSHA1(data, end - data, (SHA1Hash*)pcrDigest.buffer))
            {
                SetErr(err, TCS("hash operation failed while building policy"));
                return rc;
            }
            pcrDigest.size = sizeof(SHA1Hash);
        }
        else /* SHA256 */
        {
            if (!ComputeSHA256(data, end - data, (SHA256Hash*)pcrDigest.buffer))
            {
                SetErr(err, TCS("hash operation failed while building policy"));
                return rc;
            }
            pcrDigest.size = sizeof(SHA256Hash);
        }
    }

    /* Create the PCR policy */
    if ((rc = TPM2_PolicyPCR(
        protocol,
        policySession,
        NULL,
        &pcrDigest,
        &pcrSelectionIn,
        NULL)) != TPM_RC_SUCCESS)
    {
        SetErr(err, TCS("failed to create PCR policy"));
        return rc;
    }

    return TPM_RC_SUCCESS;
}