131 lines
4.9 KiB
C
131 lines
4.9 KiB
C
// This file was extracted from the TCG Published
|
|
// Trusted Platform Module Library
|
|
// Part 4: Supporting Routines
|
|
// Family "2.0"
|
|
// Level 00 Revision 01.16
|
|
// October 30, 2014
|
|
|
|
#include "InternalRoutines.h"
|
|
#include "Policy_spt_fp.h"
|
|
#include "PolicySigned_fp.h"
|
|
#include "PolicySecret_fp.h"
|
|
#include "PolicyTicket_fp.h"
|
|
//
|
|
//
|
|
// PolicyParameterChecks()
|
|
//
|
|
// This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The
|
|
// common parameters are nonceTPM, expiration, and cpHashA.
|
|
//
|
|
TPM_RC
|
|
PolicyParameterChecks(
|
|
SESSION *session,
|
|
UINT64 authTimeout,
|
|
TPM2B_DIGEST *cpHashA,
|
|
TPM2B_NONCE *nonce,
|
|
TPM_RC nonceParameterNumber,
|
|
TPM_RC cpHashParameterNumber,
|
|
TPM_RC expirationParameterNumber
|
|
)
|
|
{
|
|
TPM_RC result;
|
|
// Validate that input nonceTPM is correct if present
|
|
if(nonce != NULL && nonce->t.size != 0)
|
|
//
|
|
{
|
|
if(!Memory2BEqual(&nonce->b, &session->nonceTPM.b))
|
|
return TPM_RC_NONCE + RC_PolicySigned_nonceTPM;
|
|
}
|
|
// If authTimeout is set (expiration != 0...
|
|
if(authTimeout != 0)
|
|
{
|
|
// ...then nonce must be present
|
|
// nonce present isn't checked in PolicyTicket
|
|
if(nonce != NULL && nonce->t.size == 0)
|
|
// This error says that the time has expired but it is pointing
|
|
// at the nonceTPM value.
|
|
return TPM_RC_EXPIRED + nonceParameterNumber;
|
|
// Validate input expiration.
|
|
// Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE
|
|
// or TPM_RC_NV_RATE error may be returned here.
|
|
result = NvIsAvailable();
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
if(authTimeout < go.clock)
|
|
return TPM_RC_EXPIRED + expirationParameterNumber;
|
|
}
|
|
// If the cpHash is present, then check it
|
|
if(cpHashA != NULL && cpHashA->t.size != 0)
|
|
{
|
|
// The cpHash input has to have the correct size
|
|
if(cpHashA->t.size != session->u2.policyDigest.t.size)
|
|
return TPM_RC_SIZE + cpHashParameterNumber;
|
|
// If the cpHash has already been set, then this input value
|
|
// must match the current value.
|
|
if( session->u1.cpHash.b.size != 0
|
|
&& !Memory2BEqual(&cpHashA->b, &session->u1.cpHash.b))
|
|
return TPM_RC_CPHASH;
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
//
|
|
//
|
|
// PolicyContextUpdate()
|
|
//
|
|
// Update policy hash Update the policyDigest in policy session by extending policyRef and objectName to
|
|
// it. This will also update the cpHash if it is present.
|
|
//
|
|
void
|
|
PolicyContextUpdate(
|
|
TPM_CC commandCode, // IN: command code
|
|
TPM2B_NAME *name, // IN: name of entity
|
|
TPM2B_NONCE *ref, // IN: the reference data
|
|
TPM2B_DIGEST *cpHash, // IN: the cpHash (optional)
|
|
UINT64 policyTimeout,
|
|
SESSION *session // IN/OUT: policy session to be updated
|
|
)
|
|
{
|
|
HASH_STATE hashState;
|
|
UINT16 policyDigestSize;
|
|
// Start hash
|
|
policyDigestSize = CryptStartHash(session->authHashAlg, &hashState);
|
|
// policyDigest size should always be the digest size of session hash algorithm.
|
|
pAssert(session->u2.policyDigest.t.size == policyDigestSize);
|
|
// add old digest
|
|
CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
|
|
// add commandCode
|
|
CryptUpdateDigestInt(&hashState, sizeof(commandCode), &commandCode);
|
|
// add name if applicable
|
|
if(name != NULL)
|
|
CryptUpdateDigest2B(&hashState, &name->b);
|
|
// Complete the digest and get the results
|
|
CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
|
|
// Start second hash computation
|
|
CryptStartHash(session->authHashAlg, &hashState);
|
|
// add policyDigest
|
|
CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
|
|
// add policyRef
|
|
if(ref != NULL)
|
|
CryptUpdateDigest2B(&hashState, &ref->b);
|
|
// Complete second digest
|
|
CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
|
|
// Deal with the cpHash. If the cpHash value is present
|
|
// then it would have already been checked to make sure that
|
|
// it is compatible with the current value so all we need
|
|
// to do here is copy it and set the iscoHashDefined attribute
|
|
if(cpHash != NULL && cpHash->t.size != 0)
|
|
{
|
|
session->u1.cpHash = *cpHash;
|
|
session->attributes.iscpHashDefined = SET;
|
|
}
|
|
// update the timeout if it is specified
|
|
if(policyTimeout!= 0)
|
|
{
|
|
// If the timeout has not been set, then set it to the new value
|
|
if(session->timeOut == 0)
|
|
session->timeOut = policyTimeout;
|
|
else if(session->timeOut > policyTimeout)
|
|
session->timeOut = policyTimeout;
|
|
}
|
|
return;
|
|
}
|