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//
20TPM_RC
21PolicyParameterChecks(
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//
78void
79PolicyContextUpdate(
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