• 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 //** Introduction
36 /*
37     This clause contains the functions used for ticket computations.
38 */
39 
40 //** Includes
41 #include "Tpm.h"
42 
43 //** Functions
44 
45 //*** TicketIsSafe()
46 // This function indicates if producing a ticket is safe.
47 // It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE
48 // or its substring of canonical form.  If so, it is not safe to produce ticket
49 // for an input buffer claiming to be TPM generated buffer
50 //  Return Type: BOOL
51 //      TRUE(1)         safe to produce ticket
52 //      FALSE(0)        not safe to produce ticket
53 BOOL
TicketIsSafe(TPM2B * buffer)54 TicketIsSafe(
55     TPM2B           *buffer
56     )
57 {
58     TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE;
59     BYTE            bufferToCompare[sizeof(valueToCompare)];
60     BYTE            *marshalBuffer;
61 //
62     // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume
63     // it is not safe to generate a ticket
64     if(buffer->size < sizeof(valueToCompare))
65         return FALSE;
66     marshalBuffer = bufferToCompare;
67     TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL);
68     if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare)))
69         return FALSE;
70     else
71         return TRUE;
72 }
73 
74 //*** TicketComputeVerified()
75 // This function creates a TPMT_TK_VERIFIED ticket.
76 /*(See part 2 specification)
77 //  The ticket is computed as:
78 //      HMAC(proof, (TPM_ST_VERIFIED | digest | keyName))
79 //  Where:
80 //      HMAC()              an HMAC using the hash of proof
81 //      proof               a TPM secret value associated with the hierarchy
82 //                          associated with keyName
83 //      TPM_ST_VERIFIED     a value to differentiate the tickets
84 //      digest              the signed digest
85 //      keyName             the Name of the key that signed digest
86 */
87 void
TicketComputeVerified(TPMI_RH_HIERARCHY hierarchy,TPM2B_DIGEST * digest,TPM2B_NAME * keyName,TPMT_TK_VERIFIED * ticket)88 TicketComputeVerified(
89     TPMI_RH_HIERARCHY    hierarchy,     // IN: hierarchy constant for ticket
90     TPM2B_DIGEST        *digest,        // IN: digest
91     TPM2B_NAME          *keyName,       // IN: name of key that signed the values
92     TPMT_TK_VERIFIED    *ticket         // OUT: verified ticket
93     )
94 {
95     TPM2B_PROOF         *proof;
96     HMAC_STATE           hmacState;
97 //
98     // Fill in ticket fields
99     ticket->tag = TPM_ST_VERIFIED;
100     ticket->hierarchy = hierarchy;
101     proof = HierarchyGetProof(hierarchy);
102 
103     // Start HMAC using the proof value of the hierarchy as the HMAC key
104     ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
105                                              &proof->b);
106         //  TPM_ST_VERIFIED
107     CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
108         //  digest
109     CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
110         // key name
111     CryptDigestUpdate2B(&hmacState.hashState, &keyName->b);
112         // done
113     CryptHmacEnd2B(&hmacState, &ticket->digest.b);
114 
115     return;
116 }
117 
118 //*** TicketComputeAuth()
119 // This function creates a TPMT_TK_AUTH ticket.
120 /*(See part 2 specification)
121 //  The ticket is computed as:
122 //      HMAC(proof, (type || timeout || timeEpoch || cpHash
123 //                        || policyRef || keyName))
124 //  where:
125 //      HMAC()      an HMAC using the hash of proof
126 //      proof       a TPM secret value associated with the hierarchy of the key
127 //                  associated with keyName.
128 //      type        a value to differentiate the tickets.  It could be either
129 //                  TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED
130 //      timeout     TPM-specific value indicating when the authorization expires
131 //      timeEpoch   TPM-specific value indicating the epoch for the timeout
132 //      cpHash      optional hash (digest only) of the authorized command
133 //      policyRef   optional reference to a policy value
134 //      keyName name of the key that signed the authorization
135 */
136 void
TicketComputeAuth(TPM_ST type,TPMI_RH_HIERARCHY hierarchy,UINT64 timeout,BOOL expiresOnReset,TPM2B_DIGEST * cpHashA,TPM2B_NONCE * policyRef,TPM2B_NAME * entityName,TPMT_TK_AUTH * ticket)137 TicketComputeAuth(
138     TPM_ST               type,          // IN: the type of ticket.
139     TPMI_RH_HIERARCHY    hierarchy,     // IN: hierarchy constant for ticket
140     UINT64               timeout,       // IN: timeout
141     BOOL                 expiresOnReset,// IN: flag to indicate if ticket expires on
142                                         //      TPM Reset
143     TPM2B_DIGEST        *cpHashA,       // IN: input cpHashA
144     TPM2B_NONCE         *policyRef,     // IN: input policyRef
145     TPM2B_NAME          *entityName,    // IN: name of entity
146     TPMT_TK_AUTH        *ticket         // OUT: Created ticket
147     )
148 {
149     TPM2B_PROOF         *proof;
150     HMAC_STATE           hmacState;
151 //
152     // Get proper proof
153     proof = HierarchyGetProof(hierarchy);
154 
155     // Fill in ticket fields
156     ticket->tag = type;
157     ticket->hierarchy = hierarchy;
158 
159     // Start HMAC with hierarchy proof as the HMAC key
160     ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
161                                              &proof->b);
162         //  TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
163     CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag);
164     // cpHash
165     CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b);
166         //  policyRef
167     CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b);
168         //  keyName
169     CryptDigestUpdate2B(&hmacState.hashState, &entityName->b);
170         //  timeout
171     CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout);
172     if(timeout != 0)
173     {
174             //  epoch
175         CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE),
176                              g_timeEpoch);
177             // reset count
178         if(expiresOnReset)
179             CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount),
180                                  gp.totalResetCount);
181     }
182         // done
183     CryptHmacEnd2B(&hmacState, &ticket->digest.b);
184 
185     return;
186 }
187 
188 //*** TicketComputeHashCheck()
189 // This function creates a TPMT_TK_HASHCHECK ticket.
190 /*(See part 2 specification)
191 //  The ticket is computed as:
192 //      HMAC(proof, (TPM_ST_HASHCHECK || digest ))
193 //  where:
194 //      HMAC()  an HMAC using the hash of proof
195 //      proof   a TPM secret value associated with the hierarchy
196 //      TPM_ST_HASHCHECK
197 //              a value to differentiate the tickets
198 //      digest  the digest of the data
199 */
200 void
TicketComputeHashCheck(TPMI_RH_HIERARCHY hierarchy,TPM_ALG_ID hashAlg,TPM2B_DIGEST * digest,TPMT_TK_HASHCHECK * ticket)201 TicketComputeHashCheck(
202     TPMI_RH_HIERARCHY    hierarchy,     // IN: hierarchy constant for ticket
203     TPM_ALG_ID           hashAlg,       // IN: the hash algorithm for 'digest'
204     TPM2B_DIGEST        *digest,        // IN: input digest
205     TPMT_TK_HASHCHECK   *ticket         // OUT: Created ticket
206     )
207 {
208     TPM2B_PROOF         *proof;
209     HMAC_STATE           hmacState;
210 //
211     // Get proper proof
212     proof = HierarchyGetProof(hierarchy);
213 
214     // Fill in ticket fields
215     ticket->tag = TPM_ST_HASHCHECK;
216     ticket->hierarchy = hierarchy;
217 
218     // Start HMAC using hierarchy proof as HMAC key
219     ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
220                                              &proof->b);
221         //  TPM_ST_HASHCHECK
222     CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
223         //  hash algorithm
224     CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg);
225         //  digest
226     CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
227         // done
228     CryptHmacEnd2B(&hmacState, &ticket->digest.b);
229 
230     return;
231 }
232 
233 //*** TicketComputeCreation()
234 // This function creates a TPMT_TK_CREATION ticket.
235 /*(See part 2 specification)
236 // The ticket is computed as:
237 //      HMAC(proof, (TPM_ST_CREATION || Name || hash(TPMS_CREATION_DATA)))
238 //  Where:
239 //  HMAC()  an HMAC using the hash of proof
240 //  proof   a TPM secret value associated with the hierarchy associated with Name
241 //  TPM_ST_VERIFIED     a value to differentiate the tickets
242 //  Name    the Name of the object to which the creation data is to be associated
243 //  TPMS_CREATION_DATA  the creation data structure associated with Name
244 */
245 void
TicketComputeCreation(TPMI_RH_HIERARCHY hierarchy,TPM2B_NAME * name,TPM2B_DIGEST * creation,TPMT_TK_CREATION * ticket)246 TicketComputeCreation(
247     TPMI_RH_HIERARCHY    hierarchy,     // IN: hierarchy for ticket
248     TPM2B_NAME          *name,          // IN: object name
249     TPM2B_DIGEST        *creation,      // IN: creation hash
250     TPMT_TK_CREATION    *ticket         // OUT: created ticket
251     )
252 {
253     TPM2B_PROOF         *proof;
254     HMAC_STATE           hmacState;
255 
256     // Get proper proof
257     proof = HierarchyGetProof(hierarchy);
258 
259     // Fill in ticket fields
260     ticket->tag = TPM_ST_CREATION;
261     ticket->hierarchy = hierarchy;
262 
263     // Start HMAC using hierarchy proof as HMAC key
264     ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
265                                              &proof->b);
266         //  TPM_ST_CREATION
267     CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
268         //  name if provided
269     if(name != NULL)
270         CryptDigestUpdate2B(&hmacState.hashState, &name->b);
271         //  creation hash
272     CryptDigestUpdate2B(&hmacState.hashState, &creation->b);
273         // Done
274     CryptHmacEnd2B(&hmacState, &ticket->digest.b);
275 
276     return;
277 }