1 /** @file
2 Implement TPM2 EnhancedAuthorization related command.
3
4 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <IndustryStandard/UefiTcgPlatform.h>
16 #include <Library/Tpm2CommandLib.h>
17 #include <Library/Tpm2DeviceLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21
22 #pragma pack(1)
23
24 typedef struct {
25 TPM2_COMMAND_HEADER Header;
26 TPMI_DH_ENTITY AuthHandle;
27 TPMI_SH_POLICY PolicySession;
28 UINT32 AuthSessionSize;
29 TPMS_AUTH_COMMAND AuthSession;
30 TPM2B_NONCE NonceTPM;
31 TPM2B_DIGEST CpHashA;
32 TPM2B_NONCE PolicyRef;
33 INT32 Expiration;
34 } TPM2_POLICY_SECRET_COMMAND;
35
36 typedef struct {
37 TPM2_RESPONSE_HEADER Header;
38 UINT32 AuthSessionSize;
39 TPM2B_TIMEOUT Timeout;
40 TPMT_TK_AUTH PolicyTicket;
41 TPMS_AUTH_RESPONSE AuthSession;
42 } TPM2_POLICY_SECRET_RESPONSE;
43
44 typedef struct {
45 TPM2_COMMAND_HEADER Header;
46 TPMI_SH_POLICY PolicySession;
47 TPML_DIGEST HashList;
48 } TPM2_POLICY_OR_COMMAND;
49
50 typedef struct {
51 TPM2_RESPONSE_HEADER Header;
52 } TPM2_POLICY_OR_RESPONSE;
53
54 typedef struct {
55 TPM2_COMMAND_HEADER Header;
56 TPMI_SH_POLICY PolicySession;
57 TPM_CC Code;
58 } TPM2_POLICY_COMMAND_CODE_COMMAND;
59
60 typedef struct {
61 TPM2_RESPONSE_HEADER Header;
62 } TPM2_POLICY_COMMAND_CODE_RESPONSE;
63
64 typedef struct {
65 TPM2_COMMAND_HEADER Header;
66 TPMI_SH_POLICY PolicySession;
67 } TPM2_POLICY_GET_DIGEST_COMMAND;
68
69 typedef struct {
70 TPM2_RESPONSE_HEADER Header;
71 TPM2B_DIGEST PolicyHash;
72 } TPM2_POLICY_GET_DIGEST_RESPONSE;
73
74 #pragma pack()
75
76 /**
77 This command includes a secret-based authorization to a policy.
78 The caller proves knowledge of the secret value using an authorization
79 session using the authValue associated with authHandle.
80
81 @param[in] AuthHandle Handle for an entity providing the authorization
82 @param[in] PolicySession Handle for the policy session being extended.
83 @param[in] AuthSession Auth Session context
84 @param[in] NonceTPM The policy nonce for the session.
85 @param[in] CpHashA Digest of the command parameters to which this authorization is limited.
86 @param[in] PolicyRef A reference to a policy relating to the authorization.
87 @param[in] Expiration Time when authorization will expire, measured in seconds from the time that nonceTPM was generated.
88 @param[out] Timeout Time value used to indicate to the TPM when the ticket expires.
89 @param[out] PolicyTicket A ticket that includes a value indicating when the authorization expires.
90
91 @retval EFI_SUCCESS Operation completed successfully.
92 @retval EFI_DEVICE_ERROR The command was unsuccessful.
93 **/
94 EFI_STATUS
95 EFIAPI
Tpm2PolicySecret(IN TPMI_DH_ENTITY AuthHandle,IN TPMI_SH_POLICY PolicySession,IN TPMS_AUTH_COMMAND * AuthSession,OPTIONAL IN TPM2B_NONCE * NonceTPM,IN TPM2B_DIGEST * CpHashA,IN TPM2B_NONCE * PolicyRef,IN INT32 Expiration,OUT TPM2B_TIMEOUT * Timeout,OUT TPMT_TK_AUTH * PolicyTicket)96 Tpm2PolicySecret (
97 IN TPMI_DH_ENTITY AuthHandle,
98 IN TPMI_SH_POLICY PolicySession,
99 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
100 IN TPM2B_NONCE *NonceTPM,
101 IN TPM2B_DIGEST *CpHashA,
102 IN TPM2B_NONCE *PolicyRef,
103 IN INT32 Expiration,
104 OUT TPM2B_TIMEOUT *Timeout,
105 OUT TPMT_TK_AUTH *PolicyTicket
106 )
107 {
108 EFI_STATUS Status;
109 TPM2_POLICY_SECRET_COMMAND SendBuffer;
110 TPM2_POLICY_SECRET_RESPONSE RecvBuffer;
111 UINT32 SendBufferSize;
112 UINT32 RecvBufferSize;
113 UINT8 *Buffer;
114 UINT32 SessionInfoSize;
115
116 //
117 // Construct command
118 //
119 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
120 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret);
121 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
122 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
123
124 //
125 // Add in Auth session
126 //
127 Buffer = (UINT8 *)&SendBuffer.AuthSession;
128
129 // sessionInfoSize
130 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
131 Buffer += SessionInfoSize;
132 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
133
134 //
135 // Real data
136 //
137 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size));
138 Buffer += sizeof(UINT16);
139 CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size);
140 Buffer += NonceTPM->size;
141
142 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size));
143 Buffer += sizeof(UINT16);
144 CopyMem (Buffer, CpHashA->buffer, CpHashA->size);
145 Buffer += CpHashA->size;
146
147 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size));
148 Buffer += sizeof(UINT16);
149 CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size);
150 Buffer += PolicyRef->size;
151
152 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration));
153 Buffer += sizeof(UINT32);
154
155 SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
156 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
157
158 //
159 // send Tpm command
160 //
161 RecvBufferSize = sizeof (RecvBuffer);
162 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
163 if (EFI_ERROR (Status)) {
164 goto Done;
165 }
166
167 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
168 DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize));
169 Status = EFI_DEVICE_ERROR;
170 goto Done;
171 }
172 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
173 DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
174 Status = EFI_DEVICE_ERROR;
175 goto Done;
176 }
177
178 //
179 // Return the response
180 //
181 Buffer = (UINT8 *)&RecvBuffer.Timeout;
182 Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
183 Buffer += sizeof(UINT16);
184 CopyMem (Timeout->buffer, Buffer, Timeout->size);
185
186 PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
187 Buffer += sizeof(UINT16);
188 PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer));
189 Buffer += sizeof(UINT32);
190 PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
191 Buffer += sizeof(UINT16);
192 CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size);
193
194 Done:
195 //
196 // Clear AuthSession Content
197 //
198 ZeroMem (&SendBuffer, sizeof(SendBuffer));
199 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
200 return Status;
201 }
202
203 /**
204 This command allows options in authorizations without requiring that the TPM evaluate all of the options.
205 If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
206 satisfies the policy. This command will indicate that one of the required sets of conditions has been
207 satisfied.
208
209 @param[in] PolicySession Handle for the policy session being extended.
210 @param[in] HashList the list of hashes to check for a match.
211
212 @retval EFI_SUCCESS Operation completed successfully.
213 @retval EFI_DEVICE_ERROR The command was unsuccessful.
214 **/
215 EFI_STATUS
216 EFIAPI
Tpm2PolicyOR(IN TPMI_SH_POLICY PolicySession,IN TPML_DIGEST * HashList)217 Tpm2PolicyOR (
218 IN TPMI_SH_POLICY PolicySession,
219 IN TPML_DIGEST *HashList
220 )
221 {
222 EFI_STATUS Status;
223 TPM2_POLICY_OR_COMMAND SendBuffer;
224 TPM2_POLICY_OR_RESPONSE RecvBuffer;
225 UINT32 SendBufferSize;
226 UINT32 RecvBufferSize;
227 UINT8 *Buffer;
228 UINTN Index;
229
230 //
231 // Construct command
232 //
233 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
234 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR);
235
236 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
237 Buffer = (UINT8 *)&SendBuffer.HashList;
238 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count));
239 Buffer += sizeof(UINT32);
240 for (Index = 0; Index < HashList->count; Index++) {
241 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size));
242 Buffer += sizeof(UINT16);
243 CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size);
244 Buffer += HashList->digests[Index].size;
245 }
246
247 SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
248 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
249
250 //
251 // send Tpm command
252 //
253 RecvBufferSize = sizeof (RecvBuffer);
254 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
255 if (EFI_ERROR (Status)) {
256 return Status;
257 }
258
259 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
260 DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize));
261 return EFI_DEVICE_ERROR;
262 }
263 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
264 DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
265 return EFI_DEVICE_ERROR;
266 }
267
268 return EFI_SUCCESS;
269 }
270
271 /**
272 This command indicates that the authorization will be limited to a specific command code.
273
274 @param[in] PolicySession Handle for the policy session being extended.
275 @param[in] Code The allowed commandCode.
276
277 @retval EFI_SUCCESS Operation completed successfully.
278 @retval EFI_DEVICE_ERROR The command was unsuccessful.
279 **/
280 EFI_STATUS
281 EFIAPI
Tpm2PolicyCommandCode(IN TPMI_SH_POLICY PolicySession,IN TPM_CC Code)282 Tpm2PolicyCommandCode (
283 IN TPMI_SH_POLICY PolicySession,
284 IN TPM_CC Code
285 )
286 {
287 EFI_STATUS Status;
288 TPM2_POLICY_COMMAND_CODE_COMMAND SendBuffer;
289 TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer;
290 UINT32 SendBufferSize;
291 UINT32 RecvBufferSize;
292
293 //
294 // Construct command
295 //
296 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
297 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode);
298
299 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
300 SendBuffer.Code = SwapBytes32 (Code);
301
302 SendBufferSize = (UINT32) sizeof (SendBuffer);
303 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
304
305 //
306 // send Tpm command
307 //
308 RecvBufferSize = sizeof (RecvBuffer);
309 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313
314 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
315 DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize));
316 return EFI_DEVICE_ERROR;
317 }
318 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
319 DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
320 return EFI_DEVICE_ERROR;
321 }
322
323 return EFI_SUCCESS;
324 }
325
326 /**
327 This command returns the current policyDigest of the session. This command allows the TPM
328 to be used to perform the actions required to precompute the authPolicy for an object.
329
330 @param[in] PolicySession Handle for the policy session.
331 @param[out] PolicyHash the current value of the policyHash of policySession.
332
333 @retval EFI_SUCCESS Operation completed successfully.
334 @retval EFI_DEVICE_ERROR The command was unsuccessful.
335 **/
336 EFI_STATUS
337 EFIAPI
Tpm2PolicyGetDigest(IN TPMI_SH_POLICY PolicySession,OUT TPM2B_DIGEST * PolicyHash)338 Tpm2PolicyGetDigest (
339 IN TPMI_SH_POLICY PolicySession,
340 OUT TPM2B_DIGEST *PolicyHash
341 )
342 {
343 EFI_STATUS Status;
344 TPM2_POLICY_GET_DIGEST_COMMAND SendBuffer;
345 TPM2_POLICY_GET_DIGEST_RESPONSE RecvBuffer;
346 UINT32 SendBufferSize;
347 UINT32 RecvBufferSize;
348
349 //
350 // Construct command
351 //
352 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
353 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest);
354
355 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
356
357 SendBufferSize = (UINT32) sizeof (SendBuffer);
358 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
359
360 //
361 // send Tpm command
362 //
363 RecvBufferSize = sizeof (RecvBuffer);
364 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
365 if (EFI_ERROR (Status)) {
366 return Status;
367 }
368
369 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
370 DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize));
371 return EFI_DEVICE_ERROR;
372 }
373 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
374 DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
375 return EFI_DEVICE_ERROR;
376 }
377
378 //
379 // Return the response
380 //
381 PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size);
382 CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size);
383
384 return EFI_SUCCESS;
385 }
386