Coverage Report

Created: 2025-08-29 07:01

/src/libtpms/src/tpm2/Ticket.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*    Functions used for ticket computations.       */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*                    */
7
/*  Licenses and Notices              */
8
/*                    */
9
/*  1. Copyright Licenses:              */
10
/*                    */
11
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
12
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
13
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
14
/*    derivative works, distribute, display and perform the Source Code and */
15
/*    derivative works thereof, and to grant others the rights granted herein.  */
16
/*                    */
17
/*  - The TCG grants to the user of the other parts of the specification  */
18
/*    (other than the Source Code) the rights to reproduce, distribute,   */
19
/*    display, and perform the specification solely for the purpose of    */
20
/*    developing products based on such documents.        */
21
/*                    */
22
/*  2. Source Code Distribution Conditions:         */
23
/*                    */
24
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
25
/*    this list of conditions and the following disclaimers.      */
26
/*                    */
27
/*  - Redistributions in binary form must reproduce the above copyright   */
28
/*    licenses, this list of conditions and the following disclaimers in the  */
29
/*    documentation and/or other materials provided with the distribution.  */
30
/*                    */
31
/*  3. Disclaimers:               */
32
/*                    */
33
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
34
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
35
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
36
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
37
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
38
/*  information on specification licensing rights available through TCG   */
39
/*  membership agreements.              */
40
/*                    */
41
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
42
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
43
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
44
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
45
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
46
/*                    */
47
/*  - Without limitation, TCG and its members and licensors disclaim all  */
48
/*    liability, including liability for infringement of any proprietary  */
49
/*    rights, relating to use of information in this specification and to the */
50
/*    implementation of this specification, and TCG disclaims all liability for */
51
/*    cost of procurement of substitute goods or services, lost profits, loss   */
52
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
53
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
54
/*    arising in any way out of use or reliance upon this specification or any  */
55
/*    information herein.             */
56
/*                    */
57
/*  (c) Copyright IBM Corp. and others, 2016 - 2023       */
58
/*                    */
59
/********************************************************************************/
60
61
//** Introduction
62
/*
63
    This clause contains the functions used for ticket computations.
64
*/
65
66
//** Includes
67
#include "Tpm.h"
68
#include "Marshal.h"
69
70
//** Functions
71
72
//*** TicketIsSafe()
73
// This function indicates if producing a ticket is safe.
74
// It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE
75
// or its substring of canonical form.  If so, it is not safe to produce ticket
76
// for an input buffer claiming to be TPM generated buffer
77
//  Return Type: BOOL
78
//      TRUE(1)         safe to produce ticket
79
//      FALSE(0)        not safe to produce ticket
80
BOOL TicketIsSafe(TPM2B* buffer)
81
3
{
82
3
    TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE;
83
3
    BYTE            bufferToCompare[sizeof(valueToCompare)];
84
3
    BYTE*           marshalBuffer;
85
    //
86
    // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume
87
    // it is not safe to generate a ticket
88
3
    if(buffer->size < sizeof(valueToCompare))
89
0
        return FALSE;
90
3
    marshalBuffer = bufferToCompare;
91
3
    TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL);
92
3
    if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare)))
93
1
        return FALSE;
94
2
    else
95
2
        return TRUE;
96
3
}
97
98
//*** TicketComputeVerified()
99
// This function creates a TPMT_TK_VERIFIED ticket.
100
/*(See part 2 specification)
101
//  The ticket is computed as:
102
//      HMAC(proof, (TPM_ST_VERIFIED | digest | keyName))
103
//  Where:
104
//      HMAC()              an HMAC using the hash of proof
105
//      proof               a TPM secret value associated with the hierarchy
106
//                          associated with keyName
107
//      TPM_ST_VERIFIED     a value to differentiate the tickets
108
//      digest              the signed digest
109
//      keyName             the Name of the key that signed digest
110
*/
111
TPM_RC TicketComputeVerified(
112
    TPMI_RH_HIERARCHY hierarchy,  // IN: hierarchy constant for ticket
113
    TPM2B_DIGEST*     digest,     // IN: digest
114
    TPM2B_NAME*       keyName,    // IN: name of key that signed the values
115
    TPMT_TK_VERIFIED* ticket      // OUT: verified ticket
116
)
117
0
{
118
0
    TPM_RC      result = TPM_RC_SUCCESS;
119
0
    TPM2B_PROOF proof;
120
0
    HMAC_STATE  hmacState;
121
    //
122
    // Fill in ticket fields
123
0
    ticket->tag       = TPM_ST_VERIFIED;
124
0
    ticket->hierarchy = hierarchy;
125
0
    result            = HierarchyGetProof(hierarchy, &proof);
126
0
    if(result != TPM_RC_SUCCESS)
127
0
        return result;
128
129
    // Start HMAC using the proof value of the hierarchy as the HMAC key
130
0
    ticket->digest.t.size =
131
0
        CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof.b);
132
0
    MemorySet(proof.b.buffer, 0, proof.b.size);
133
134
    //  TPM_ST_VERIFIED
135
0
    CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
136
    //  digest
137
0
    CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
138
    // key name
139
0
    CryptDigestUpdate2B(&hmacState.hashState, &keyName->b);
140
    // done
141
0
    CryptHmacEnd2B(&hmacState, &ticket->digest.b);
142
143
0
    return TPM_RC_SUCCESS;
144
0
}
145
146
//*** TicketComputeAuth()
147
// This function creates a TPMT_TK_AUTH ticket.
148
/*(See part 2 specification)
149
//  The ticket is computed as:
150
//      HMAC(proof, (type || timeout || timeEpoch || cpHash
151
//                        || policyRef || keyName))
152
//  where:
153
//      HMAC()      an HMAC using the hash of proof
154
//      proof       a TPM secret value associated with the hierarchy of the key
155
//                  associated with keyName.
156
//      type        a value to differentiate the tickets.  It could be either
157
//                  TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED
158
//      timeout     TPM-specific value indicating when the authorization expires
159
//      timeEpoch   TPM-specific value indicating the epoch for the timeout
160
//      cpHash      optional hash (digest only) of the authorized command
161
//      policyRef   optional reference to a policy value
162
//      keyName name of the key that signed the authorization
163
*/
164
TPM_RC TicketComputeAuth(
165
    TPM_ST            type,            // IN: the type of ticket.
166
    TPMI_RH_HIERARCHY hierarchy,       // IN: hierarchy constant for ticket
167
    UINT64            timeout,         // IN: timeout
168
    BOOL              expiresOnReset,  // IN: flag to indicate if ticket expires on
169
                                       //      TPM Reset
170
    TPM2B_DIGEST* cpHashA,             // IN: input cpHashA
171
    TPM2B_NONCE*  policyRef,           // IN: input policyRef
172
    TPM2B_NAME*   entityName,          // IN: name of entity
173
    TPMT_TK_AUTH* ticket               // OUT: Created ticket
174
)
175
0
{
176
0
    TPM_RC      result = TPM_RC_SUCCESS;
177
0
    TPM2B_PROOF proof;
178
0
    HMAC_STATE  hmacState;
179
    //
180
    // Get proper proof
181
0
    result = HierarchyGetProof(hierarchy, &proof);
182
0
    if(result != TPM_RC_SUCCESS)
183
0
        return result;
184
185
    // Fill in ticket fields
186
0
    ticket->tag       = type;
187
0
    ticket->hierarchy = hierarchy;
188
189
    // Start HMAC with hierarchy proof as the HMAC key
190
0
    ticket->digest.t.size =
191
0
        CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof.b);
192
0
    MemorySet(proof.b.buffer, 0, proof.b.size);
193
194
    //  TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
195
0
    CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag);
196
    // cpHash
197
0
    CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b);
198
    //  policyRef
199
0
    CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b);
200
    //  keyName
201
0
    CryptDigestUpdate2B(&hmacState.hashState, &entityName->b);
202
    //  timeout
203
0
    CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout);
204
0
    if(timeout != 0)
205
0
    {
206
        //  epoch
207
0
        CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE), g_timeEpoch);
208
        // reset count
209
0
        if(expiresOnReset)
210
0
            CryptDigestUpdateInt(
211
0
                &hmacState.hashState, sizeof(gp.totalResetCount), gp.totalResetCount);
212
0
    }
213
    // done
214
0
    CryptHmacEnd2B(&hmacState, &ticket->digest.b);
215
216
0
    return TPM_RC_SUCCESS;
217
0
}
218
219
//*** TicketComputeHashCheck()
220
// This function creates a TPMT_TK_HASHCHECK ticket.
221
/*(See part 2 specification)
222
//  The ticket is computed as:
223
//      HMAC(proof, (TPM_ST_HASHCHECK || digest ))
224
//  where:
225
//      HMAC()  an HMAC using the hash of proof
226
//      proof   a TPM secret value associated with the hierarchy
227
//      TPM_ST_HASHCHECK
228
//              a value to differentiate the tickets
229
//      digest  the digest of the data
230
*/
231
TPM_RC TicketComputeHashCheck(
232
    TPMI_RH_HIERARCHY  hierarchy,  // IN: hierarchy constant for ticket
233
    TPM_ALG_ID         hashAlg,    // IN: the hash algorithm for 'digest'
234
    TPM2B_DIGEST*      digest,     // IN: input digest
235
    TPMT_TK_HASHCHECK* ticket      // OUT: Created ticket
236
)
237
4
{
238
4
    TPM_RC      result = TPM_RC_SUCCESS;
239
4
    TPM2B_PROOF proof;
240
4
    HMAC_STATE  hmacState;
241
    //
242
    // Get proper proof
243
4
    result = HierarchyGetProof(hierarchy, &proof);
244
4
    if(result != TPM_RC_SUCCESS)
245
0
        return result;
246
247
    // Fill in ticket fields
248
4
    ticket->tag       = TPM_ST_HASHCHECK;
249
4
    ticket->hierarchy = hierarchy;
250
251
    // Start HMAC using hierarchy proof as HMAC key
252
4
    ticket->digest.t.size =
253
4
        CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof.b);
254
4
    MemorySet(proof.b.buffer, 0, proof.b.size);
255
256
    //  TPM_ST_HASHCHECK
257
4
    CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
258
    //  hash algorithm
259
4
    CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg);
260
    //  digest
261
4
    CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
262
    // done
263
4
    CryptHmacEnd2B(&hmacState, &ticket->digest.b);
264
265
4
    return TPM_RC_SUCCESS;
266
4
}
267
268
//*** TicketComputeCreation()
269
// This function creates a TPMT_TK_CREATION ticket.
270
/*(See part 2 specification)
271
// The ticket is computed as:
272
//      HMAC(proof, (TPM_ST_CREATION || Name || hash(TPMS_CREATION_DATA)))
273
//  Where:
274
//  HMAC()  an HMAC using the hash of proof
275
//  proof   a TPM secret value associated with the hierarchy associated with Name
276
//  TPM_ST_VERIFIED     a value to differentiate the tickets
277
//  Name    the Name of the object to which the creation data is to be associated
278
//  TPMS_CREATION_DATA  the creation data structure associated with Name
279
*/
280
TPM_RC TicketComputeCreation(TPMI_RH_HIERARCHY hierarchy,  // IN: hierarchy for ticket
281
                             TPM2B_NAME*       name,       // IN: object name
282
                             TPM2B_DIGEST*     creation,   // IN: creation hash
283
                             TPMT_TK_CREATION* ticket      // OUT: created ticket
284
)
285
87
{
286
87
    TPM_RC      result = TPM_RC_SUCCESS;
287
87
    TPM2B_PROOF proof;
288
87
    HMAC_STATE  hmacState;
289
290
    // Get proper proof
291
87
    result = HierarchyGetProof(hierarchy, &proof);
292
87
    if(result != TPM_RC_SUCCESS)
293
0
        return result;
294
295
    // Fill in ticket fields
296
87
    ticket->tag       = TPM_ST_CREATION;
297
87
    ticket->hierarchy = hierarchy;
298
299
    // Start HMAC using hierarchy proof as HMAC key
300
87
    ticket->digest.t.size =
301
87
        CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof.b);
302
87
    MemorySet(proof.b.buffer, 0, proof.b.size);
303
304
    //  TPM_ST_CREATION
305
87
    CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
306
    //  name if provided
307
87
    if(name != NULL)
308
87
        CryptDigestUpdate2B(&hmacState.hashState, &name->b);
309
    //  creation hash
310
87
    CryptDigestUpdate2B(&hmacState.hashState, &creation->b);
311
    // Done
312
87
    CryptHmacEnd2B(&hmacState, &ticket->digest.b);
313
314
87
    return TPM_RC_SUCCESS;
315
87
}