/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 | } |