• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Includes
36 #include "Tpm.h"
37 #include "Policy_spt_fp.h"
38 #include "PolicySigned_fp.h"
39 #include "PolicySecret_fp.h"
40 #include "PolicyTicket_fp.h"
41 
42 //** Functions
43 //*** PolicyParameterChecks()
44 // This function validates the common parameters of TPM2_PolicySiged()
45 // and TPM2_PolicySecret(). The common parameters are 'nonceTPM',
46 // 'expiration', and 'cpHashA'.
47 TPM_RC
PolicyParameterChecks(SESSION * session,UINT64 authTimeout,TPM2B_DIGEST * cpHashA,TPM2B_NONCE * nonce,TPM_RC blameNonce,TPM_RC blameCpHash,TPM_RC blameExpiration)48 PolicyParameterChecks(
49     SESSION         *session,
50     UINT64           authTimeout,
51     TPM2B_DIGEST    *cpHashA,
52     TPM2B_NONCE     *nonce,
53     TPM_RC           blameNonce,
54     TPM_RC           blameCpHash,
55     TPM_RC           blameExpiration
56     )
57 {
58     // Validate that input nonceTPM is correct if present
59     if(nonce != NULL && nonce->t.size != 0)
60     {
61         if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b))
62             return TPM_RCS_NONCE + blameNonce;
63     }
64     // If authTimeout is set (expiration != 0...
65     if(authTimeout != 0)
66     {
67         // Validate input expiration.
68         // Cannot compare time if clock stop advancing.  A TPM_RC_NV_UNAVAILABLE
69         // or TPM_RC_NV_RATE error may be returned here.
70         RETURN_IF_NV_IS_NOT_AVAILABLE;
71 
72         // if the time has already passed or the time epoch has changed then the
73         // time value is no longer good.
74         if((authTimeout < g_time)
75            || (session->epoch != g_timeEpoch))
76             return TPM_RCS_EXPIRED + blameExpiration;
77     }
78     // If the cpHash is present, then check it
79     if(cpHashA != NULL && cpHashA->t.size != 0)
80     {
81         // The cpHash input has to have the correct size
82         if(cpHashA->t.size != session->u2.policyDigest.t.size)
83             return TPM_RCS_SIZE + blameCpHash;
84 
85         // If the cpHash has already been set, then this input value
86         // must match the current value.
87         if(session->u1.cpHash.b.size != 0
88            && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b))
89             return TPM_RC_CPHASH;
90     }
91     return TPM_RC_SUCCESS;
92 }
93 
94 //*** PolicyContextUpdate()
95 // Update policy hash
96 //      Update the policyDigest in policy session by extending policyRef and
97 //      objectName to it. This will also update the cpHash if it is present.
98 //
99 //  Return Type: void
100 void
PolicyContextUpdate(TPM_CC commandCode,TPM2B_NAME * name,TPM2B_NONCE * ref,TPM2B_DIGEST * cpHash,UINT64 policyTimeout,SESSION * session)101 PolicyContextUpdate(
102     TPM_CC           commandCode,   // IN: command code
103     TPM2B_NAME      *name,          // IN: name of entity
104     TPM2B_NONCE     *ref,           // IN: the reference data
105     TPM2B_DIGEST    *cpHash,        // IN: the cpHash (optional)
106     UINT64           policyTimeout, // IN: the timeout value for the policy
107     SESSION         *session        // IN/OUT: policy session to be updated
108     )
109 {
110     HASH_STATE           hashState;
111 
112     // Start hash
113    CryptHashStart(&hashState, session->authHashAlg);
114 
115 
116     // policyDigest size should always be the digest size of session hash algorithm.
117     pAssert(session->u2.policyDigest.t.size
118             == CryptHashGetDigestSize(session->authHashAlg));
119 
120     // add old digest
121     CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
122 
123     // add commandCode
124     CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode);
125 
126     // add name if applicable
127     if(name != NULL)
128         CryptDigestUpdate2B(&hashState, &name->b);
129 
130     // Complete the digest and get the results
131     CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
132 
133     // If the policy reference is not null, do a second update to the digest.
134     if(ref != NULL)
135     {
136 
137         // Start second hash computation
138         CryptHashStart(&hashState, session->authHashAlg);
139 
140         // add policyDigest
141         CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
142 
143         // add policyRef
144         CryptDigestUpdate2B(&hashState, &ref->b);
145 
146         // Complete second digest
147         CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
148     }
149     // Deal with the cpHash. If the cpHash value is present
150     // then it would have already been checked to make sure that
151     // it is compatible with the current value so all we need
152     // to do here is copy it and set the isCpHashDefined attribute
153     if(cpHash != NULL && cpHash->t.size != 0)
154     {
155         session->u1.cpHash = *cpHash;
156         session->attributes.isCpHashDefined = SET;
157     }
158 
159     // update the timeout if it is specified
160     if(policyTimeout != 0)
161     {
162         // If the timeout has not been set, then set it to the new value
163         // than the current timeout then set it to the new value
164         if(session->timeout == 0 || session->timeout > policyTimeout)
165             session->timeout = policyTimeout;
166     }
167     return;
168 }
169 //*** ComputeAuthTimeout()
170 // This function is used to determine what the authorization timeout value for
171 // the session should be.
172 UINT64
ComputeAuthTimeout(SESSION * session,INT32 expiration,TPM2B_NONCE * nonce)173 ComputeAuthTimeout(
174     SESSION         *session,               // IN: the session containing the time
175                                             //     values
176     INT32            expiration,            // IN: either the number of seconds from
177                                             //     the start of the session or the
178                                             //     time in g_timer;
179     TPM2B_NONCE     *nonce                  // IN: indicator of the time base
180     )
181 {
182     UINT64           policyTime;
183     // If no expiration, policy time is 0
184     if(expiration == 0)
185         policyTime = 0;
186     else
187     {
188         if(expiration < 0)
189             expiration = -expiration;
190         if(nonce->t.size == 0)
191             // The input time is absolute Time (not Clock), but it is expressed
192             // in seconds. To make sure that we don't time out too early, take the
193             // current value of milliseconds in g_time and add that to the input
194             // seconds value.
195             policyTime = (((UINT64)expiration) * 1000) + g_time % 1000;
196         else
197             // The policy timeout is the absolute value of the expiration in seconds
198             // added to the start time of the policy.
199             policyTime = session->startTime + (((UINT64)expiration) * 1000);
200 
201     }
202     return policyTime;
203 }
204 
205 //*** PolicyDigestClear()
206 // Function to reset the policyDigest of a session
207 void
PolicyDigestClear(SESSION * session)208 PolicyDigestClear(
209     SESSION         *session
210     )
211 {
212     session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);
213     MemorySet(session->u2.policyDigest.t.buffer, 0,
214               session->u2.policyDigest.t.size);
215 }
216 
217 //*** PolicySptCheckCondition()
218 // Checks to see if the condition in the policy is satisfied.
219 BOOL
PolicySptCheckCondition(TPM_EO operation,BYTE * opA,BYTE * opB,UINT16 size)220 PolicySptCheckCondition(
221     TPM_EO          operation,
222     BYTE            *opA,
223     BYTE            *opB,
224     UINT16           size
225     )
226 {
227     // Arithmetic Comparison
228     switch(operation)
229     {
230         case TPM_EO_EQ:
231             // compare A = B
232             return (UnsignedCompareB(size, opA, size, opB) == 0);
233             break;
234         case TPM_EO_NEQ:
235             // compare A != B
236             return (UnsignedCompareB(size, opA, size, opB) != 0);
237             break;
238         case TPM_EO_SIGNED_GT:
239             // compare A > B signed
240             return (SignedCompareB(size, opA, size, opB) > 0);
241             break;
242         case TPM_EO_UNSIGNED_GT:
243             // compare A > B unsigned
244             return (UnsignedCompareB(size, opA, size, opB) > 0);
245             break;
246         case TPM_EO_SIGNED_LT:
247             // compare A < B signed
248             return (SignedCompareB(size, opA, size, opB) < 0);
249             break;
250         case TPM_EO_UNSIGNED_LT:
251             // compare A < B unsigned
252             return (UnsignedCompareB(size, opA, size, opB) < 0);
253             break;
254         case TPM_EO_SIGNED_GE:
255             // compare A >= B signed
256             return (SignedCompareB(size, opA, size, opB) >= 0);
257             break;
258         case TPM_EO_UNSIGNED_GE:
259             // compare A >= B unsigned
260             return (UnsignedCompareB(size, opA, size, opB) >= 0);
261             break;
262         case TPM_EO_SIGNED_LE:
263             // compare A <= B signed
264             return (SignedCompareB(size, opA, size, opB) <= 0);
265             break;
266         case TPM_EO_UNSIGNED_LE:
267             // compare A <= B unsigned
268             return (UnsignedCompareB(size, opA, size, opB) <= 0);
269             break;
270         case TPM_EO_BITSET:
271             // All bits SET in B are SET in A. ((A&B)=B)
272         {
273             UINT32 i;
274             for(i = 0; i < size; i++)
275                 if((opA[i] & opB[i]) != opB[i])
276                     return FALSE;
277         }
278         break;
279         case TPM_EO_BITCLEAR:
280             // All bits SET in B are CLEAR in A. ((A&B)=0)
281         {
282             UINT32 i;
283             for(i = 0; i < size; i++)
284                 if((opA[i] & opB[i]) != 0)
285                     return FALSE;
286         }
287         break;
288         default:
289             FAIL(FATAL_ERROR_INTERNAL);
290             break;
291     }
292     return TRUE;
293 }
294