1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include   "InternalRoutines.h"
9 #include   "Policy_spt_fp.h"
10 #include   "PolicySigned_fp.h"
11 #include   "PolicySecret_fp.h"
12 #include   "PolicyTicket_fp.h"
13 //
14 //
15 //           PolicyParameterChecks()
16 //
17 //      This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The
18 //      common parameters are nonceTPM, expiration, and cpHashA.
19 //
20 TPM_RC
PolicyParameterChecks(SESSION * session,UINT64 authTimeout,TPM2B_DIGEST * cpHashA,TPM2B_NONCE * nonce,TPM_RC nonceParameterNumber,TPM_RC cpHashParameterNumber,TPM_RC expirationParameterNumber)21 PolicyParameterChecks(
22      SESSION          *session,
23      UINT64            authTimeout,
24      TPM2B_DIGEST     *cpHashA,
25      TPM2B_NONCE      *nonce,
26      TPM_RC            nonceParameterNumber,
27      TPM_RC            cpHashParameterNumber,
28      TPM_RC            expirationParameterNumber
29      )
30 {
31      TPM_RC            result;
32      // Validate that input nonceTPM is correct if present
33      if(nonce != NULL && nonce->t.size != 0)
34 //
35    {
36          if(!Memory2BEqual(&nonce->b, &session->nonceTPM.b))
37              return TPM_RC_NONCE + RC_PolicySigned_nonceTPM;
38    }
39    // If authTimeout is set (expiration != 0...
40    if(authTimeout != 0)
41    {
42        // ...then nonce must be present
43        // nonce present isn't checked in PolicyTicket
44        if(nonce != NULL && nonce->t.size == 0)
45            // This error says that the time has expired but it is pointing
46            // at the nonceTPM value.
47            return TPM_RC_EXPIRED + nonceParameterNumber;
48          // Validate input expiration.
49          // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE
50          // or TPM_RC_NV_RATE error may be returned here.
51          result = NvIsAvailable();
52          if(result != TPM_RC_SUCCESS)
53              return result;
54          if(authTimeout < go.clock)
55              return TPM_RC_EXPIRED + expirationParameterNumber;
56    }
57    // If the cpHash is present, then check it
58    if(cpHashA != NULL && cpHashA->t.size != 0)
59    {
60        // The cpHash input has to have the correct size
61        if(cpHashA->t.size != session->u2.policyDigest.t.size)
62            return TPM_RC_SIZE + cpHashParameterNumber;
63          // If the cpHash has already been set, then this input value
64          // must match the current value.
65          if(     session->u1.cpHash.b.size != 0
66              && !Memory2BEqual(&cpHashA->b, &session->u1.cpHash.b))
67                  return TPM_RC_CPHASH;
68    }
69    return TPM_RC_SUCCESS;
70 }
71 //
72 //
73 //          PolicyContextUpdate()
74 //
75 //     Update policy hash Update the policyDigest in policy session by extending policyRef and objectName to
76 //     it. This will also update the cpHash if it is present.
77 //
78 void
PolicyContextUpdate(TPM_CC commandCode,TPM2B_NAME * name,TPM2B_NONCE * ref,TPM2B_DIGEST * cpHash,UINT64 policyTimeout,SESSION * session)79 PolicyContextUpdate(
80    TPM_CC              commandCode,     //   IN:   command code
81    TPM2B_NAME         *name,            //   IN:   name of entity
82    TPM2B_NONCE        *ref,             //   IN:   the reference data
83    TPM2B_DIGEST       *cpHash,          //   IN:   the cpHash (optional)
84    UINT64              policyTimeout,
85    SESSION            *session          // IN/OUT: policy session to be updated
86    )
87 {
88    HASH_STATE               hashState;
89    UINT16                   policyDigestSize;
90    // Start hash
91    policyDigestSize = CryptStartHash(session->authHashAlg, &hashState);
92    // policyDigest size should always be the digest size of session hash algorithm.
93    pAssert(session->u2.policyDigest.t.size == policyDigestSize);
94      // add old digest
95      CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
96      // add commandCode
97      CryptUpdateDigestInt(&hashState, sizeof(commandCode), &commandCode);
98      // add name if applicable
99      if(name != NULL)
100          CryptUpdateDigest2B(&hashState, &name->b);
101      // Complete the digest and get the results
102      CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
103      // Start second hash computation
104      CryptStartHash(session->authHashAlg, &hashState);
105      // add policyDigest
106      CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
107      // add policyRef
108      if(ref != NULL)
109          CryptUpdateDigest2B(&hashState, &ref->b);
110      // Complete second digest
111      CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
112      // Deal with the cpHash. If the cpHash value is present
113      // then it would have already been checked to make sure that
114      // it is compatible with the current value so all we need
115      // to do here is copy it and set the iscoHashDefined attribute
116      if(cpHash != NULL && cpHash->t.size != 0)
117      {
118          session->u1.cpHash = *cpHash;
119          session->attributes.iscpHashDefined = SET;
120      }
121      // update the timeout if it is specified
122      if(policyTimeout!= 0)
123      {
124      // If the timeout has not been set, then set it to the new value
125          if(session->timeOut == 0)
126              session->timeOut = policyTimeout;
127          else if(session->timeOut > policyTimeout)
128              session->timeOut = policyTimeout;
129      }
130      return;
131 }
132