Coverage Report

Created: 2025-07-23 06:19

/src/ibmswtpm2/src/Policy_spt.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*                  */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: Policy_spt.c 953 2017-03-06 20:31:40Z kgoldman $   */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016          */
59
/*                    */
60
/********************************************************************************/
61
62
/* 7.4 Policy Command Support (Policy_spt.c) */
63
#include "Tpm.h"
64
#include "Policy_spt_fp.h"
65
#include "PolicySigned_fp.h"
66
#include "PolicySecret_fp.h"
67
#include "PolicyTicket_fp.h"
68
/* 7.4.1 PolicyParameterChecks() */
69
/* This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The
70
   common parameters are nonceTPM, expiration, and cpHashA. */
71
TPM_RC
72
PolicyParameterChecks(
73
          SESSION         *session,
74
          UINT64           authTimeout,
75
          TPM2B_DIGEST    *cpHashA,
76
          TPM2B_NONCE     *nonce,
77
          TPM_RC           blameNonce,
78
          TPM_RC           blameCpHash,
79
          TPM_RC           blameExpiration
80
          )
81
0
{
82
    // Validate that input nonceTPM is correct if present
83
0
    if(nonce != NULL && nonce->t.size != 0)
84
0
  {
85
0
      if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b))
86
0
    return TPM_RCS_NONCE + blameNonce;
87
0
  }
88
    // If authTimeout is set (expiration != 0...
89
0
    if(authTimeout != 0)
90
0
  {
91
      // Validate input expiration.
92
      // Cannot compare time if clock stop advancing.  A TPM_RC_NV_UNAVAILABLE
93
      // or TPM_RC_NV_RATE error may be returned here.
94
0
      RETURN_IF_NV_IS_NOT_AVAILABLE;
95
      // if the time has already passed or the time epoch has changed then the
96
      // time value is no longer good.
97
0
      if((authTimeout < g_time)
98
0
         || (session->epoch != g_timeEpoch))
99
0
    return TPM_RCS_EXPIRED + blameExpiration;
100
0
  }
101
    // If the cpHash is present, then check it
102
0
    if(cpHashA != NULL && cpHashA->t.size != 0)
103
0
  {
104
      // The cpHash input has to have the correct size
105
0
      if(cpHashA->t.size != session->u2.policyDigest.t.size)
106
0
    return TPM_RCS_SIZE + blameCpHash;
107
      // If the cpHash has already been set, then this input value
108
      // must match the current value.
109
0
      if(session->u1.cpHash.b.size != 0
110
0
         && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b))
111
0
    return TPM_RC_CPHASH;
112
0
  }
113
0
    return TPM_RC_SUCCESS;
114
0
}
115
/* 7.4.2 PolicyContextUpdate() */
116
/* Update policy hash Update the policyDigest in policy session by extending policyRef and
117
   objectName to it. This will also update the cpHash if it is present. */
118
void
119
PolicyContextUpdate(
120
        TPM_CC           commandCode,   // IN: command code
121
        TPM2B_NAME      *name,          // IN: name of entity
122
        TPM2B_NONCE     *ref,           // IN: the reference data
123
        TPM2B_DIGEST    *cpHash,        // IN: the cpHash (optional)
124
        UINT64           policyTimeout, // IN: the timeout value for the policy
125
        SESSION         *session        // IN/OUT: policy session to be updated
126
        )
127
0
{
128
0
    HASH_STATE           hashState;
129
    // Start hash
130
0
    CryptHashStart(&hashState, session->authHashAlg);
131
    // policyDigest size should always be the digest size of session hash algorithm.
132
0
    pAssert(session->u2.policyDigest.t.size
133
0
      == CryptHashGetDigestSize(session->authHashAlg));
134
    // add old digest
135
0
    CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
136
    // add commandCode
137
0
    CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode);
138
    // add name if applicable
139
0
    if(name != NULL)
140
0
  CryptDigestUpdate2B(&hashState, &name->b);
141
    // Complete the digest and get the results
142
0
    CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
143
    // If the policy reference is not null, do a second update to the digest.
144
0
    if(ref != NULL)
145
0
  {
146
      // Start second hash computation
147
0
      CryptHashStart(&hashState, session->authHashAlg);
148
      // add policyDigest
149
0
      CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
150
      // add policyRef
151
0
      CryptDigestUpdate2B(&hashState, &ref->b);
152
      // Complete second digest
153
0
      CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
154
0
  }
155
    // Deal with the cpHash. If the cpHash value is present
156
    // then it would have already been checked to make sure that
157
    // it is compatible with the current value so all we need
158
    // to do here is copy it and set the isCpHashDefined attribute
159
0
    if(cpHash != NULL && cpHash->t.size != 0)
160
0
  {
161
0
      session->u1.cpHash = *cpHash;
162
0
      session->attributes.isCpHashDefined = SET;
163
0
  }
164
    // update the timeout if it is specified
165
0
    if(policyTimeout != 0)
166
0
  {
167
      // If the timeout has not been set, then set it to the new value
168
      // than the current timeout then set it to the new value
169
0
      if(session->timeout == 0 || session->timeout > policyTimeout)
170
0
    session->timeout = policyTimeout;
171
0
  }
172
0
    return;
173
0
}
174
/* 7.4.2.1 ComputeAuthTimeout() */
175
/* This function is used to determine what the authorization timeout value for the session should
176
   be. */
177
UINT64
178
ComputeAuthTimeout(
179
       SESSION         *session,               // IN: the session containing the time
180
       //     values
181
       INT32            expiration,            // IN: either the number of seconds from
182
       //     the start of the session or the
183
       //     time in g_timer;
184
       TPM2B_NONCE     *nonce                  // IN: indicator of the time base
185
       )
186
0
{
187
0
    UINT64           policyTime;
188
    // If no expiration, policy time is 0
189
0
    if(expiration == 0)
190
0
  policyTime = 0;
191
0
    else
192
0
  {
193
0
      if(expiration < 0)
194
0
    expiration = -expiration;
195
0
      if(nonce->t.size == 0)
196
    // The input time is absolute Time (not Clock), but it is expressed
197
    // in seconds. To make sure that we don't time out too early, take the
198
    // current value of milliseconds in g_time and add that to the input
199
    // seconds value.
200
0
    policyTime = (((UINT64)expiration) * 1000) + g_time % 1000;
201
0
      else
202
    // The policy timeout is the absolute value of the expiration in seconds
203
    // added to the start time of the policy.
204
0
    policyTime = session->startTime + (((UINT64)expiration) * 1000);
205
0
  }
206
0
    return policyTime;
207
0
}
208
/* 7.4.2.2 PolicyDigestClear() */
209
/* Function to reset the policyDigest of a session */
210
void
211
PolicyDigestClear(
212
      SESSION         *session
213
      )
214
0
{
215
0
    session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg);
216
0
    MemorySet(session->u2.policyDigest.t.buffer, 0,
217
0
        session->u2.policyDigest.t.size);
218
0
}
219
BOOL
220
PolicySptCheckCondition(
221
      TPM_EO          operation,
222
      BYTE            *opA,
223
      BYTE            *opB,
224
      UINT16           size
225
      )
226
0
{
227
    // Arithmetic Comparison
228
0
    switch(operation)
229
0
  {
230
0
    case TPM_EO_EQ:
231
      // compare A = B
232
0
      return (UnsignedCompareB(size, opA, size, opB) == 0);
233
0
      break;
234
0
    case TPM_EO_NEQ:
235
      // compare A != B
236
0
      return (UnsignedCompareB(size, opA, size, opB) != 0);
237
0
      break;
238
0
    case TPM_EO_SIGNED_GT:
239
      // compare A > B signed
240
0
      return (SignedCompareB(size, opA, size, opB) > 0);
241
0
      break;
242
0
    case TPM_EO_UNSIGNED_GT:
243
      // compare A > B unsigned
244
0
      return (UnsignedCompareB(size, opA, size, opB) > 0);
245
0
      break;
246
0
    case TPM_EO_SIGNED_LT:
247
      // compare A < B signed
248
0
      return (SignedCompareB(size, opA, size, opB) < 0);
249
0
      break;
250
0
    case TPM_EO_UNSIGNED_LT:
251
      // compare A < B unsigned
252
0
      return (UnsignedCompareB(size, opA, size, opB) < 0);
253
0
      break;
254
0
    case TPM_EO_SIGNED_GE:
255
      // compare A >= B signed
256
0
      return (SignedCompareB(size, opA, size, opB) >= 0);
257
0
      break;
258
0
    case TPM_EO_UNSIGNED_GE:
259
      // compare A >= B unsigned
260
0
      return (UnsignedCompareB(size, opA, size, opB) >= 0);
261
0
      break;
262
0
    case TPM_EO_SIGNED_LE:
263
      // compare A <= B signed
264
0
      return (SignedCompareB(size, opA, size, opB) <= 0);
265
0
      break;
266
0
    case TPM_EO_UNSIGNED_LE:
267
      // compare A <= B unsigned
268
0
      return (UnsignedCompareB(size, opA, size, opB) <= 0);
269
0
      break;
270
0
    case TPM_EO_BITSET:
271
      // All bits SET in B are SET in A. ((A&B)=B)
272
0
        {
273
0
      UINT32 i;
274
0
      for(i = 0; i < size; i++)
275
0
          if((opA[i] & opB[i]) != opB[i])
276
0
        return FALSE;
277
0
        }
278
0
        break;
279
0
    case TPM_EO_BITCLEAR:
280
      // All bits SET in B are CLEAR in A. ((A&B)=0)
281
0
        {
282
0
      UINT32 i;
283
0
      for(i = 0; i < size; i++)
284
0
          if((opA[i] & opB[i]) != 0)
285
0
        return FALSE;
286
0
        }
287
0
        break;
288
0
    default:
289
0
      FAIL(FATAL_ERROR_INTERNAL);
290
0
      break;
291
0
  }
292
0
    return TRUE;
293
0
}