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 }