1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen /*
37*5c591343SA. Cody Schuffelen This clause contains the functions used for ticket computations.
38*5c591343SA. Cody Schuffelen */
39*5c591343SA. Cody Schuffelen
40*5c591343SA. Cody Schuffelen //** Includes
41*5c591343SA. Cody Schuffelen #include "Tpm.h"
42*5c591343SA. Cody Schuffelen
43*5c591343SA. Cody Schuffelen //** Functions
44*5c591343SA. Cody Schuffelen
45*5c591343SA. Cody Schuffelen //*** TicketIsSafe()
46*5c591343SA. Cody Schuffelen // This function indicates if producing a ticket is safe.
47*5c591343SA. Cody Schuffelen // It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE
48*5c591343SA. Cody Schuffelen // or its substring of canonical form. If so, it is not safe to produce ticket
49*5c591343SA. Cody Schuffelen // for an input buffer claiming to be TPM generated buffer
50*5c591343SA. Cody Schuffelen // Return Type: BOOL
51*5c591343SA. Cody Schuffelen // TRUE(1) safe to produce ticket
52*5c591343SA. Cody Schuffelen // FALSE(0) not safe to produce ticket
53*5c591343SA. Cody Schuffelen BOOL
TicketIsSafe(TPM2B * buffer)54*5c591343SA. Cody Schuffelen TicketIsSafe(
55*5c591343SA. Cody Schuffelen TPM2B *buffer
56*5c591343SA. Cody Schuffelen )
57*5c591343SA. Cody Schuffelen {
58*5c591343SA. Cody Schuffelen TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE;
59*5c591343SA. Cody Schuffelen BYTE bufferToCompare[sizeof(valueToCompare)];
60*5c591343SA. Cody Schuffelen BYTE *marshalBuffer;
61*5c591343SA. Cody Schuffelen //
62*5c591343SA. Cody Schuffelen // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume
63*5c591343SA. Cody Schuffelen // it is not safe to generate a ticket
64*5c591343SA. Cody Schuffelen if(buffer->size < sizeof(valueToCompare))
65*5c591343SA. Cody Schuffelen return FALSE;
66*5c591343SA. Cody Schuffelen marshalBuffer = bufferToCompare;
67*5c591343SA. Cody Schuffelen TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL);
68*5c591343SA. Cody Schuffelen if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare)))
69*5c591343SA. Cody Schuffelen return FALSE;
70*5c591343SA. Cody Schuffelen else
71*5c591343SA. Cody Schuffelen return TRUE;
72*5c591343SA. Cody Schuffelen }
73*5c591343SA. Cody Schuffelen
74*5c591343SA. Cody Schuffelen //*** TicketComputeVerified()
75*5c591343SA. Cody Schuffelen // This function creates a TPMT_TK_VERIFIED ticket.
76*5c591343SA. Cody Schuffelen /*(See part 2 specification)
77*5c591343SA. Cody Schuffelen // The ticket is computed as:
78*5c591343SA. Cody Schuffelen // HMAC(proof, (TPM_ST_VERIFIED | digest | keyName))
79*5c591343SA. Cody Schuffelen // Where:
80*5c591343SA. Cody Schuffelen // HMAC() an HMAC using the hash of proof
81*5c591343SA. Cody Schuffelen // proof a TPM secret value associated with the hierarchy
82*5c591343SA. Cody Schuffelen // associated with keyName
83*5c591343SA. Cody Schuffelen // TPM_ST_VERIFIED a value to differentiate the tickets
84*5c591343SA. Cody Schuffelen // digest the signed digest
85*5c591343SA. Cody Schuffelen // keyName the Name of the key that signed digest
86*5c591343SA. Cody Schuffelen */
87*5c591343SA. Cody Schuffelen void
TicketComputeVerified(TPMI_RH_HIERARCHY hierarchy,TPM2B_DIGEST * digest,TPM2B_NAME * keyName,TPMT_TK_VERIFIED * ticket)88*5c591343SA. Cody Schuffelen TicketComputeVerified(
89*5c591343SA. Cody Schuffelen TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket
90*5c591343SA. Cody Schuffelen TPM2B_DIGEST *digest, // IN: digest
91*5c591343SA. Cody Schuffelen TPM2B_NAME *keyName, // IN: name of key that signed the values
92*5c591343SA. Cody Schuffelen TPMT_TK_VERIFIED *ticket // OUT: verified ticket
93*5c591343SA. Cody Schuffelen )
94*5c591343SA. Cody Schuffelen {
95*5c591343SA. Cody Schuffelen TPM2B_PROOF *proof;
96*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
97*5c591343SA. Cody Schuffelen //
98*5c591343SA. Cody Schuffelen // Fill in ticket fields
99*5c591343SA. Cody Schuffelen ticket->tag = TPM_ST_VERIFIED;
100*5c591343SA. Cody Schuffelen ticket->hierarchy = hierarchy;
101*5c591343SA. Cody Schuffelen proof = HierarchyGetProof(hierarchy);
102*5c591343SA. Cody Schuffelen
103*5c591343SA. Cody Schuffelen // Start HMAC using the proof value of the hierarchy as the HMAC key
104*5c591343SA. Cody Schuffelen ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
105*5c591343SA. Cody Schuffelen &proof->b);
106*5c591343SA. Cody Schuffelen // TPM_ST_VERIFIED
107*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
108*5c591343SA. Cody Schuffelen // digest
109*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
110*5c591343SA. Cody Schuffelen // key name
111*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &keyName->b);
112*5c591343SA. Cody Schuffelen // done
113*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &ticket->digest.b);
114*5c591343SA. Cody Schuffelen
115*5c591343SA. Cody Schuffelen return;
116*5c591343SA. Cody Schuffelen }
117*5c591343SA. Cody Schuffelen
118*5c591343SA. Cody Schuffelen //*** TicketComputeAuth()
119*5c591343SA. Cody Schuffelen // This function creates a TPMT_TK_AUTH ticket.
120*5c591343SA. Cody Schuffelen /*(See part 2 specification)
121*5c591343SA. Cody Schuffelen // The ticket is computed as:
122*5c591343SA. Cody Schuffelen // HMAC(proof, (type || timeout || timeEpoch || cpHash
123*5c591343SA. Cody Schuffelen // || policyRef || keyName))
124*5c591343SA. Cody Schuffelen // where:
125*5c591343SA. Cody Schuffelen // HMAC() an HMAC using the hash of proof
126*5c591343SA. Cody Schuffelen // proof a TPM secret value associated with the hierarchy of the key
127*5c591343SA. Cody Schuffelen // associated with keyName.
128*5c591343SA. Cody Schuffelen // type a value to differentiate the tickets. It could be either
129*5c591343SA. Cody Schuffelen // TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED
130*5c591343SA. Cody Schuffelen // timeout TPM-specific value indicating when the authorization expires
131*5c591343SA. Cody Schuffelen // timeEpoch TPM-specific value indicating the epoch for the timeout
132*5c591343SA. Cody Schuffelen // cpHash optional hash (digest only) of the authorized command
133*5c591343SA. Cody Schuffelen // policyRef optional reference to a policy value
134*5c591343SA. Cody Schuffelen // keyName name of the key that signed the authorization
135*5c591343SA. Cody Schuffelen */
136*5c591343SA. Cody Schuffelen 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*5c591343SA. Cody Schuffelen TicketComputeAuth(
138*5c591343SA. Cody Schuffelen TPM_ST type, // IN: the type of ticket.
139*5c591343SA. Cody Schuffelen TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket
140*5c591343SA. Cody Schuffelen UINT64 timeout, // IN: timeout
141*5c591343SA. Cody Schuffelen BOOL expiresOnReset,// IN: flag to indicate if ticket expires on
142*5c591343SA. Cody Schuffelen // TPM Reset
143*5c591343SA. Cody Schuffelen TPM2B_DIGEST *cpHashA, // IN: input cpHashA
144*5c591343SA. Cody Schuffelen TPM2B_NONCE *policyRef, // IN: input policyRef
145*5c591343SA. Cody Schuffelen TPM2B_NAME *entityName, // IN: name of entity
146*5c591343SA. Cody Schuffelen TPMT_TK_AUTH *ticket // OUT: Created ticket
147*5c591343SA. Cody Schuffelen )
148*5c591343SA. Cody Schuffelen {
149*5c591343SA. Cody Schuffelen TPM2B_PROOF *proof;
150*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
151*5c591343SA. Cody Schuffelen //
152*5c591343SA. Cody Schuffelen // Get proper proof
153*5c591343SA. Cody Schuffelen proof = HierarchyGetProof(hierarchy);
154*5c591343SA. Cody Schuffelen
155*5c591343SA. Cody Schuffelen // Fill in ticket fields
156*5c591343SA. Cody Schuffelen ticket->tag = type;
157*5c591343SA. Cody Schuffelen ticket->hierarchy = hierarchy;
158*5c591343SA. Cody Schuffelen
159*5c591343SA. Cody Schuffelen // Start HMAC with hierarchy proof as the HMAC key
160*5c591343SA. Cody Schuffelen ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
161*5c591343SA. Cody Schuffelen &proof->b);
162*5c591343SA. Cody Schuffelen // TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
163*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag);
164*5c591343SA. Cody Schuffelen // cpHash
165*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b);
166*5c591343SA. Cody Schuffelen // policyRef
167*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b);
168*5c591343SA. Cody Schuffelen // keyName
169*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &entityName->b);
170*5c591343SA. Cody Schuffelen // timeout
171*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout);
172*5c591343SA. Cody Schuffelen if(timeout != 0)
173*5c591343SA. Cody Schuffelen {
174*5c591343SA. Cody Schuffelen // epoch
175*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE),
176*5c591343SA. Cody Schuffelen g_timeEpoch);
177*5c591343SA. Cody Schuffelen // reset count
178*5c591343SA. Cody Schuffelen if(expiresOnReset)
179*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount),
180*5c591343SA. Cody Schuffelen gp.totalResetCount);
181*5c591343SA. Cody Schuffelen }
182*5c591343SA. Cody Schuffelen // done
183*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &ticket->digest.b);
184*5c591343SA. Cody Schuffelen
185*5c591343SA. Cody Schuffelen return;
186*5c591343SA. Cody Schuffelen }
187*5c591343SA. Cody Schuffelen
188*5c591343SA. Cody Schuffelen //*** TicketComputeHashCheck()
189*5c591343SA. Cody Schuffelen // This function creates a TPMT_TK_HASHCHECK ticket.
190*5c591343SA. Cody Schuffelen /*(See part 2 specification)
191*5c591343SA. Cody Schuffelen // The ticket is computed as:
192*5c591343SA. Cody Schuffelen // HMAC(proof, (TPM_ST_HASHCHECK || digest ))
193*5c591343SA. Cody Schuffelen // where:
194*5c591343SA. Cody Schuffelen // HMAC() an HMAC using the hash of proof
195*5c591343SA. Cody Schuffelen // proof a TPM secret value associated with the hierarchy
196*5c591343SA. Cody Schuffelen // TPM_ST_HASHCHECK
197*5c591343SA. Cody Schuffelen // a value to differentiate the tickets
198*5c591343SA. Cody Schuffelen // digest the digest of the data
199*5c591343SA. Cody Schuffelen */
200*5c591343SA. Cody Schuffelen void
TicketComputeHashCheck(TPMI_RH_HIERARCHY hierarchy,TPM_ALG_ID hashAlg,TPM2B_DIGEST * digest,TPMT_TK_HASHCHECK * ticket)201*5c591343SA. Cody Schuffelen TicketComputeHashCheck(
202*5c591343SA. Cody Schuffelen TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket
203*5c591343SA. Cody Schuffelen TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest'
204*5c591343SA. Cody Schuffelen TPM2B_DIGEST *digest, // IN: input digest
205*5c591343SA. Cody Schuffelen TPMT_TK_HASHCHECK *ticket // OUT: Created ticket
206*5c591343SA. Cody Schuffelen )
207*5c591343SA. Cody Schuffelen {
208*5c591343SA. Cody Schuffelen TPM2B_PROOF *proof;
209*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
210*5c591343SA. Cody Schuffelen //
211*5c591343SA. Cody Schuffelen // Get proper proof
212*5c591343SA. Cody Schuffelen proof = HierarchyGetProof(hierarchy);
213*5c591343SA. Cody Schuffelen
214*5c591343SA. Cody Schuffelen // Fill in ticket fields
215*5c591343SA. Cody Schuffelen ticket->tag = TPM_ST_HASHCHECK;
216*5c591343SA. Cody Schuffelen ticket->hierarchy = hierarchy;
217*5c591343SA. Cody Schuffelen
218*5c591343SA. Cody Schuffelen // Start HMAC using hierarchy proof as HMAC key
219*5c591343SA. Cody Schuffelen ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
220*5c591343SA. Cody Schuffelen &proof->b);
221*5c591343SA. Cody Schuffelen // TPM_ST_HASHCHECK
222*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
223*5c591343SA. Cody Schuffelen // hash algorithm
224*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg);
225*5c591343SA. Cody Schuffelen // digest
226*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &digest->b);
227*5c591343SA. Cody Schuffelen // done
228*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &ticket->digest.b);
229*5c591343SA. Cody Schuffelen
230*5c591343SA. Cody Schuffelen return;
231*5c591343SA. Cody Schuffelen }
232*5c591343SA. Cody Schuffelen
233*5c591343SA. Cody Schuffelen //*** TicketComputeCreation()
234*5c591343SA. Cody Schuffelen // This function creates a TPMT_TK_CREATION ticket.
235*5c591343SA. Cody Schuffelen /*(See part 2 specification)
236*5c591343SA. Cody Schuffelen // The ticket is computed as:
237*5c591343SA. Cody Schuffelen // HMAC(proof, (TPM_ST_CREATION || Name || hash(TPMS_CREATION_DATA)))
238*5c591343SA. Cody Schuffelen // Where:
239*5c591343SA. Cody Schuffelen // HMAC() an HMAC using the hash of proof
240*5c591343SA. Cody Schuffelen // proof a TPM secret value associated with the hierarchy associated with Name
241*5c591343SA. Cody Schuffelen // TPM_ST_VERIFIED a value to differentiate the tickets
242*5c591343SA. Cody Schuffelen // Name the Name of the object to which the creation data is to be associated
243*5c591343SA. Cody Schuffelen // TPMS_CREATION_DATA the creation data structure associated with Name
244*5c591343SA. Cody Schuffelen */
245*5c591343SA. Cody Schuffelen void
TicketComputeCreation(TPMI_RH_HIERARCHY hierarchy,TPM2B_NAME * name,TPM2B_DIGEST * creation,TPMT_TK_CREATION * ticket)246*5c591343SA. Cody Schuffelen TicketComputeCreation(
247*5c591343SA. Cody Schuffelen TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket
248*5c591343SA. Cody Schuffelen TPM2B_NAME *name, // IN: object name
249*5c591343SA. Cody Schuffelen TPM2B_DIGEST *creation, // IN: creation hash
250*5c591343SA. Cody Schuffelen TPMT_TK_CREATION *ticket // OUT: created ticket
251*5c591343SA. Cody Schuffelen )
252*5c591343SA. Cody Schuffelen {
253*5c591343SA. Cody Schuffelen TPM2B_PROOF *proof;
254*5c591343SA. Cody Schuffelen HMAC_STATE hmacState;
255*5c591343SA. Cody Schuffelen
256*5c591343SA. Cody Schuffelen // Get proper proof
257*5c591343SA. Cody Schuffelen proof = HierarchyGetProof(hierarchy);
258*5c591343SA. Cody Schuffelen
259*5c591343SA. Cody Schuffelen // Fill in ticket fields
260*5c591343SA. Cody Schuffelen ticket->tag = TPM_ST_CREATION;
261*5c591343SA. Cody Schuffelen ticket->hierarchy = hierarchy;
262*5c591343SA. Cody Schuffelen
263*5c591343SA. Cody Schuffelen // Start HMAC using hierarchy proof as HMAC key
264*5c591343SA. Cody Schuffelen ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG,
265*5c591343SA. Cody Schuffelen &proof->b);
266*5c591343SA. Cody Schuffelen // TPM_ST_CREATION
267*5c591343SA. Cody Schuffelen CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag);
268*5c591343SA. Cody Schuffelen // name if provided
269*5c591343SA. Cody Schuffelen if(name != NULL)
270*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &name->b);
271*5c591343SA. Cody Schuffelen // creation hash
272*5c591343SA. Cody Schuffelen CryptDigestUpdate2B(&hmacState.hashState, &creation->b);
273*5c591343SA. Cody Schuffelen // Done
274*5c591343SA. Cody Schuffelen CryptHmacEnd2B(&hmacState, &ticket->digest.b);
275*5c591343SA. Cody Schuffelen
276*5c591343SA. Cody Schuffelen return;
277*5c591343SA. Cody Schuffelen }