]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
SecurityPkg Tpm2CommandLib: Fix TPM2.0 response memory overflow
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2EnhancedAuthorization.c
1 /** @file
2 Implement TPM2 EnhancedAuthorization related command.
3
4 Copyright (c) 2014 - 2018, 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
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 if (Timeout->size > sizeof(UINT64)) {
184 DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - Timeout->size error %x\n", Timeout->size));
185 Status = EFI_DEVICE_ERROR;
186 goto Done;
187 }
188
189 Buffer += sizeof(UINT16);
190 CopyMem (Timeout->buffer, Buffer, Timeout->size);
191
192 PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
193 Buffer += sizeof(UINT16);
194 PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer));
195 Buffer += sizeof(UINT32);
196 PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
197 Buffer += sizeof(UINT16);
198 if (PolicyTicket->digest.size > sizeof(TPMU_HA)) {
199 DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - digest.size error %x\n", PolicyTicket->digest.size));
200 Status = EFI_DEVICE_ERROR;
201 goto Done;
202 }
203
204 CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size);
205
206 Done:
207 //
208 // Clear AuthSession Content
209 //
210 ZeroMem (&SendBuffer, sizeof(SendBuffer));
211 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
212 return Status;
213 }
214
215 /**
216 This command allows options in authorizations without requiring that the TPM evaluate all of the options.
217 If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
218 satisfies the policy. This command will indicate that one of the required sets of conditions has been
219 satisfied.
220
221 @param[in] PolicySession Handle for the policy session being extended.
222 @param[in] HashList the list of hashes to check for a match.
223
224 @retval EFI_SUCCESS Operation completed successfully.
225 @retval EFI_DEVICE_ERROR The command was unsuccessful.
226 **/
227 EFI_STATUS
228 EFIAPI
229 Tpm2PolicyOR (
230 IN TPMI_SH_POLICY PolicySession,
231 IN TPML_DIGEST *HashList
232 )
233 {
234 EFI_STATUS Status;
235 TPM2_POLICY_OR_COMMAND SendBuffer;
236 TPM2_POLICY_OR_RESPONSE RecvBuffer;
237 UINT32 SendBufferSize;
238 UINT32 RecvBufferSize;
239 UINT8 *Buffer;
240 UINTN Index;
241
242 //
243 // Construct command
244 //
245 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
246 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR);
247
248 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
249 Buffer = (UINT8 *)&SendBuffer.HashList;
250 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count));
251 Buffer += sizeof(UINT32);
252 for (Index = 0; Index < HashList->count; Index++) {
253 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size));
254 Buffer += sizeof(UINT16);
255 CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size);
256 Buffer += HashList->digests[Index].size;
257 }
258
259 SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
260 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
261
262 //
263 // send Tpm command
264 //
265 RecvBufferSize = sizeof (RecvBuffer);
266 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
267 if (EFI_ERROR (Status)) {
268 return Status;
269 }
270
271 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
272 DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize));
273 return EFI_DEVICE_ERROR;
274 }
275 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
276 DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
277 return EFI_DEVICE_ERROR;
278 }
279
280 return EFI_SUCCESS;
281 }
282
283 /**
284 This command indicates that the authorization will be limited to a specific command code.
285
286 @param[in] PolicySession Handle for the policy session being extended.
287 @param[in] Code The allowed commandCode.
288
289 @retval EFI_SUCCESS Operation completed successfully.
290 @retval EFI_DEVICE_ERROR The command was unsuccessful.
291 **/
292 EFI_STATUS
293 EFIAPI
294 Tpm2PolicyCommandCode (
295 IN TPMI_SH_POLICY PolicySession,
296 IN TPM_CC Code
297 )
298 {
299 EFI_STATUS Status;
300 TPM2_POLICY_COMMAND_CODE_COMMAND SendBuffer;
301 TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer;
302 UINT32 SendBufferSize;
303 UINT32 RecvBufferSize;
304
305 //
306 // Construct command
307 //
308 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
309 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode);
310
311 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
312 SendBuffer.Code = SwapBytes32 (Code);
313
314 SendBufferSize = (UINT32) sizeof (SendBuffer);
315 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
316
317 //
318 // send Tpm command
319 //
320 RecvBufferSize = sizeof (RecvBuffer);
321 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
322 if (EFI_ERROR (Status)) {
323 return Status;
324 }
325
326 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
327 DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize));
328 return EFI_DEVICE_ERROR;
329 }
330 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
331 DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
332 return EFI_DEVICE_ERROR;
333 }
334
335 return EFI_SUCCESS;
336 }
337
338 /**
339 This command returns the current policyDigest of the session. This command allows the TPM
340 to be used to perform the actions required to precompute the authPolicy for an object.
341
342 @param[in] PolicySession Handle for the policy session.
343 @param[out] PolicyHash the current value of the policyHash of policySession.
344
345 @retval EFI_SUCCESS Operation completed successfully.
346 @retval EFI_DEVICE_ERROR The command was unsuccessful.
347 **/
348 EFI_STATUS
349 EFIAPI
350 Tpm2PolicyGetDigest (
351 IN TPMI_SH_POLICY PolicySession,
352 OUT TPM2B_DIGEST *PolicyHash
353 )
354 {
355 EFI_STATUS Status;
356 TPM2_POLICY_GET_DIGEST_COMMAND SendBuffer;
357 TPM2_POLICY_GET_DIGEST_RESPONSE RecvBuffer;
358 UINT32 SendBufferSize;
359 UINT32 RecvBufferSize;
360
361 //
362 // Construct command
363 //
364 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
365 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest);
366
367 SendBuffer.PolicySession = SwapBytes32 (PolicySession);
368
369 SendBufferSize = (UINT32) sizeof (SendBuffer);
370 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
371
372 //
373 // send Tpm command
374 //
375 RecvBufferSize = sizeof (RecvBuffer);
376 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
377 if (EFI_ERROR (Status)) {
378 return Status;
379 }
380
381 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
382 DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize));
383 return EFI_DEVICE_ERROR;
384 }
385 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
386 DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
387 return EFI_DEVICE_ERROR;
388 }
389
390 //
391 // Return the response
392 //
393 PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size);
394 if (PolicyHash->size > sizeof(TPMU_HA)) {
395 DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - PolicyHash->size error %x\n", PolicyHash->size));
396 return EFI_DEVICE_ERROR;
397 }
398
399 CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size);
400
401 return EFI_SUCCESS;
402 }