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