]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeTcgPhysicalPresenceStorageLib/DxeTcgPhysicalPresenceStorage.c
SecurityPkg: Add DxeTcgPhysicalPresenceStorageLib.
[mirror_edk2.git] / SecurityPkg / Library / DxeTcgPhysicalPresenceStorageLib / DxeTcgPhysicalPresenceStorage.c
1 /** @file
2 Tcg PP storage library instance that does support any storage specific PPI.
3
4 Copyright (c) 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 #include <PiDxe.h>
15
16 #include <Guid/PhysicalPresenceData.h>
17 #include <Guid/TcgPhysicalPresenceStorageData.h>
18
19 #include <IndustryStandard/TcgPhysicalPresence.h>
20
21
22 #include <Protocol/VariableLock.h>
23
24 #include <Library/DebugLib.h>
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/UefiRuntimeServicesTableLib.h>
27 #include <Library/UefiDriverEntryPoint.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/UefiLib.h>
30 #include <Library/MemoryAllocationLib.h>
31 #include <Library/PrintLib.h>
32 #include <Library/HiiLib.h>
33 #include <Library/HobLib.h>
34 #include <Library/TcgPhysicalPresenceStorageLib.h>
35
36 #include "DxeTcgPhysicalPresenceStorageLibInternal.h"
37
38 /**
39 Display the confirm text and get user confirmation.
40
41 @param[in] OperationRequest TPM physical presence operation request.
42 @param[in] ManagementFlags BIOS TPM Management Flags.
43
44
45 @retval TRUE The user need to confirme the changes.
46 @retval FALSE The user doesn't need to confirme the changes.
47 **/
48 BOOLEAN
49 TcgPpNeedUserConfirm (
50 IN UINT8 OperationRequest,
51 IN UINT32 ManagementFlags
52 )
53 {
54 BOOLEAN NeedUserConfirm;
55
56 NeedUserConfirm = FALSE;
57
58 switch (OperationRequest) {
59 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
60 if ((ManagementFlags & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) != 0) {
61 NeedUserConfirm = TRUE;
62 }
63 break;
64
65 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
66 if ((ManagementFlags & TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) != 0) {
67 NeedUserConfirm = TRUE;
68 }
69 break;
70
71 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
72 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
73 NeedUserConfirm = TRUE;
74 break;
75
76 default:
77 break;
78 }
79
80 return NeedUserConfirm;
81 }
82
83 /**
84 The handler for TPM physical presence function:
85 Submit TPM Operation Request to Pre-OS Environment and
86 Submit TPM Operation Request to Pre-OS Environment 2.
87
88 Caution: This function may receive untrusted input.
89
90 @param[in] OperationRequest TPM physical presence operation request.
91 @param[in] RequestParameter TPM physical presence operation request parameter.
92
93 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
94 Submit TPM Operation Request to Pre-OS Environment 2.
95 **/
96 UINT32
97 EFIAPI
98 TcgSubmitStorageRequest (
99 IN UINT32 OperationRequest,
100 IN UINT32 RequestParameter
101 )
102 {
103 EFI_STATUS Status;
104 UINTN DataSize;
105 EFI_PHYSICAL_PRESENCE PpData;
106
107 DEBUG ((EFI_D_INFO, "[TPM Storage] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
108
109 //
110 // Get the Physical Presence storage variable
111 //
112 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
113 Status = gRT->GetVariable (
114 PHYSICAL_PRESENCE_VARIABLE,
115 &gEfiPhysicalPresenceGuid,
116 NULL,
117 &DataSize,
118 &PpData
119 );
120 if (EFI_ERROR (Status)) {
121 DEBUG ((EFI_D_ERROR, "[TPM Storage] Get PP variable failure! Status = %r\n", Status));
122 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
123 }
124
125 if ((OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) &&
126 (OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
127 //
128 // This library only support storage related actions.
129 //
130 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
131 }
132
133 if (PpData.PPRequest != OperationRequest) {
134 PpData.PPRequest = (UINT8)OperationRequest;
135 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
136 Status = gRT->SetVariable (
137 PHYSICAL_PRESENCE_VARIABLE,
138 &gEfiPhysicalPresenceGuid,
139 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
140 DataSize,
141 &PpData
142 );
143 }
144
145 if (EFI_ERROR (Status)) {
146 DEBUG ((EFI_D_ERROR, "[TPM Storage] Set PP variable failure! Status = %r\n", Status));
147 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
148 }
149
150 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
151 }
152
153 /**
154 Check if the pending TPM request needs user input to confirm.
155
156 The TPM request may come from OS. This API will check if TPM request exists and need user
157 input to confirmation.
158
159 @retval TRUE TPM needs input to confirm user physical presence.
160 @retval FALSE TPM doesn't need input to confirm user physical presence.
161
162 **/
163 BOOLEAN
164 EFIAPI
165 TcgNeedUserConfirm(
166 VOID
167 )
168 {
169 EFI_STATUS Status;
170 EFI_PHYSICAL_PRESENCE TcgPpData;
171 UINTN DataSize;
172 EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS PpiFlags;
173
174 //
175 // Check S4 resume
176 //
177 if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
178 DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
179 return FALSE;
180 }
181
182 //
183 // Check Tpm requests
184 //
185 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
186 Status = gRT->GetVariable (
187 PHYSICAL_PRESENCE_VARIABLE,
188 &gEfiPhysicalPresenceGuid,
189 NULL,
190 &DataSize,
191 &TcgPpData
192 );
193 if (EFI_ERROR (Status)) {
194 return FALSE;
195 }
196
197 DataSize = sizeof (EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS);
198 Status = gRT->GetVariable (
199 TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE,
200 &gEfiTcgPhysicalPresenceStorageGuid,
201 NULL,
202 &DataSize,
203 &PpiFlags
204 );
205 if (EFI_ERROR (Status)) {
206 PpiFlags.PPFlags = TCG_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
207 }
208
209 if ((TcgPpData.PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) &&
210 (TcgPpData.PPRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
211 //
212 // This library only support storage related actions.
213 //
214 return FALSE;
215 }
216
217 return TcgPpNeedUserConfirm(TcgPpData.PPRequest, PpiFlags.PPFlags);
218 }
219
220 /**
221 The handler for TPM physical presence function:
222 Return TPM Operation Response to OS Environment.
223
224 @param[out] MostRecentRequest Most recent operation request.
225 @param[out] Response Response to the most recent operation request.
226
227 @return Return Code for Return TPM Operation Response to OS Environment.
228 **/
229 UINT32
230 EFIAPI
231 TcgReturnOperationResponseToOsFunction (
232 OUT UINT32 *MostRecentRequest,
233 OUT UINT32 *Response
234 )
235 {
236 EFI_STATUS Status;
237 UINTN DataSize;
238 EFI_PHYSICAL_PRESENCE PpData;
239
240 DEBUG ((EFI_D_INFO, "[TPM Storage] ReturnOperationResponseToOsFunction\n"));
241
242 //
243 // Get the Physical Presence variable
244 //
245 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
246 Status = gRT->GetVariable (
247 PHYSICAL_PRESENCE_VARIABLE,
248 &gEfiPhysicalPresenceGuid,
249 NULL,
250 &DataSize,
251 &PpData
252 );
253 if (EFI_ERROR (Status)) {
254 *MostRecentRequest = 0;
255 *Response = 0;
256 DEBUG ((EFI_D_ERROR, "[TPM Storage] Get PP variable failure! Status = %r\n", Status));
257 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
258 }
259
260 *MostRecentRequest = PpData.LastPPRequest;
261 *Response = PpData.PPResponse;
262
263 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
264 }
265
266 /**
267 Check and execute the requested physical presence command.
268
269 This API should be invoked in BIOS boot phase to process pending request.
270
271 Caution: This function may receive untrusted input.
272
273 If OperationRequest < 128, then ASSERT().
274
275 @param[in] OperationRequest TPM physical presence operation request.
276 @param[in, out] ManagementFlags BIOS TPM Management Flags.
277 @param[out] ResetRequired If reset is required to vendor settings in effect.
278 True, it indicates the reset is required.
279 False, it indicates the reset is not required.
280
281 @return TPM Operation Response to OS Environment.
282 **/
283 UINT32
284 TcgExecutePendingRequest (
285 IN UINT8 OperationRequest,
286 IN OUT UINT8 *ManagementFlags,
287 OUT BOOLEAN *ResetRequired
288 )
289 {
290 ASSERT ((OperationRequest >= TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) &&
291 (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION));
292
293 if (TcgPpNeedUserConfirm(OperationRequest, *ManagementFlags)) {
294 if (!TcgPpUserConfirm (OperationRequest)) {
295 return TCG_PP_OPERATION_RESPONSE_USER_ABORT;
296 }
297 }
298
299 switch (OperationRequest) {
300 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
301 *ManagementFlags |= TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
302 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
303
304 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
305 *ManagementFlags &= ~TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
306 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
307
308 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
309 *ManagementFlags |= TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
310 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
311
312 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
313 *ManagementFlags &= ~TCG_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
314 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
315
316 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
317 *ManagementFlags |= TCG_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
318 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
319
320 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
321 *ManagementFlags &= ~TCG_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
322 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
323
324 default:
325 break;
326 }
327
328 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
329 }
330
331 /**
332 Check and execute the pending TPM request.
333
334 The TPM request may come from OS or BIOS. This API will display request information and wait
335 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
336 the TPM request is confirmed, and one or more reset may be required to make TPM request to
337 take effect.
338
339 This API should be invoked after console in and console out are all ready as they are required
340 to display request information and get user input to confirm the request.
341
342 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
343 **/
344 VOID
345 EFIAPI
346 TcgProcessStorageRequest (
347 VOID
348 )
349 {
350 EFI_STATUS Status;
351 UINTN DataSize;
352 EFI_PHYSICAL_PRESENCE TcgPpData;
353 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;
354 EFI_PHYSICAL_PRESENCE_FLAGS PpiFlags;
355 EFI_PHYSICAL_PRESENCE_FLAGS NewPpiFlags;
356 BOOLEAN ResetRequired;
357
358 //
359 // Check S4 resume
360 //
361 if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
362 DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
363 return ;
364 }
365
366 //
367 // Initialize physical presence variable.
368 //
369 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
370 Status = gRT->GetVariable (
371 PHYSICAL_PRESENCE_VARIABLE,
372 &gEfiPhysicalPresenceGuid,
373 NULL,
374 &DataSize,
375 &TcgPpData
376 );
377 if (EFI_ERROR (Status)) {
378 ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
379 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
380 Status = gRT->SetVariable (
381 PHYSICAL_PRESENCE_VARIABLE,
382 &gEfiPhysicalPresenceGuid,
383 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
384 DataSize,
385 &TcgPpData
386 );
387 if (EFI_ERROR (Status)) {
388 DEBUG ((EFI_D_ERROR, "[TPM Storage] Set physical presence variable failed, Status = %r\n", Status));
389 return ;
390 }
391 }
392
393 if ((TcgPpData.PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) ||
394 (TcgPpData.PPRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
395 //
396 // This library only support storage related actions.
397 //
398 DEBUG ((EFI_D_INFO, "[TPM Storage] Only support TCG storage related PP actions, not support PPRequest=%x\n", TcgPpData.PPRequest));
399 return;
400 }
401
402 //
403 // Initialize physical presence storage flags.
404 //
405 DataSize = sizeof (EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS);
406 Status = gRT->GetVariable (
407 TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE,
408 &gEfiTcgPhysicalPresenceStorageGuid,
409 NULL,
410 &DataSize,
411 &PpiFlags
412 );
413 if (EFI_ERROR (Status)) {
414 PpiFlags.PPFlags = TCG_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
415 Status = gRT->SetVariable (
416 TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE,
417 &gEfiTcgPhysicalPresenceStorageGuid,
418 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
419 sizeof (EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS),
420 &PpiFlags
421 );
422 if (EFI_ERROR (Status)) {
423 DEBUG ((EFI_D_ERROR, "[TPM Storage] Set physical presence flag failed, Status = %r\n", Status));
424 return ;
425 }
426 }
427 DEBUG ((EFI_D_INFO, "[TPM Storage] PpiFlags = %x\n", PpiFlags.PPFlags));
428
429 //
430 // This flags variable controls whether physical presence is required for TPM command.
431 // It should be protected from malicious software. We set it as read-only variable here.
432 //
433 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
434 if (!EFI_ERROR (Status)) {
435 Status = VariableLockProtocol->RequestToLock (
436 VariableLockProtocol,
437 TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE,
438 &gEfiTcgPhysicalPresenceStorageGuid
439 );
440 if (EFI_ERROR (Status)) {
441 DEBUG ((EFI_D_ERROR, "[TPM Storage] Error when lock variable %s, Status = %r\n", TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE, Status));
442 ASSERT_EFI_ERROR (Status);
443 }
444 }
445
446 DEBUG ((EFI_D_INFO, "[TPM Storage] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
447
448 NewPpiFlags.PPFlags = PpiFlags.PPFlags;
449 ResetRequired = FALSE;
450 TcgPpData.PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
451
452 TcgPpData.PPResponse = TcgExecutePendingRequest (TcgPpData.PPRequest, &NewPpiFlags.PPFlags, &ResetRequired);
453 DEBUG ((EFI_D_INFO, "[TPM Storage] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
454
455 if (TcgPpData.PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
456 return;
457 }
458
459 //
460 // Save the flags if it is updated.
461 //
462 if (CompareMem (&PpiFlags, &NewPpiFlags, sizeof(EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS)) != 0) {
463 Status = gRT->SetVariable (
464 TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS_VARIABLE,
465 &gEfiTcgPhysicalPresenceStorageGuid,
466 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
467 sizeof (EFI_TCG_PHYSICAL_PRESENCE_STORAGE_FLAGS),
468 &NewPpiFlags
469 );
470 }
471
472 //
473 // Clear request
474 //
475 TcgPpData.LastPPRequest = TcgPpData.PPRequest;
476 TcgPpData.PPRequest = TCG_PHYSICAL_PRESENCE_NO_ACTION;
477
478 //
479 // Save changes
480 //
481 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
482 Status = gRT->SetVariable (
483 PHYSICAL_PRESENCE_VARIABLE,
484 &gEfiPhysicalPresenceGuid,
485 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
486 DataSize,
487 &TcgPpData
488 );
489 if (EFI_ERROR (Status)) {
490 return;
491 }
492
493 if (!ResetRequired) {
494 return;
495 }
496
497 Print (L"Rebooting system to make TPM2 settings in effect\n");
498 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
499 ASSERT (FALSE);
500 }
501