1 /** @file
2 Handle TPM 2.0 physical presence requests from OS.
3
4 This library will handle TPM 2.0 physical presence request from OS.
5
6 Caution: This module requires additional review when modified.
7 This driver will have external input - variable.
8 This external input must be validated carefully to avoid security issue.
9
10 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
11 will receive untrusted input and do validation.
12
13 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
18
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21
22 **/
23
24 #include <PiSmm.h>
25
26 #include <Guid/Tcg2PhysicalPresenceData.h>
27
28 #include <Protocol/SmmVariable.h>
29
30 #include <Library/DebugLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/Tcg2PpVendorLib.h>
33 #include <Library/SmmServicesTableLib.h>
34
35 EFI_SMM_VARIABLE_PROTOCOL *mTcg2PpSmmVariable;
36
37 /**
38 The handler for TPM physical presence function:
39 Return TPM Operation Response to OS Environment.
40
41 This API should be invoked in OS runtime phase to interface with ACPI method.
42
43 @param[out] MostRecentRequest Most recent operation request.
44 @param[out] Response Response to the most recent operation request.
45
46 @return Return Code for Return TPM Operation Response to OS Environment.
47 **/
48 UINT32
49 EFIAPI
Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction(OUT UINT32 * MostRecentRequest,OUT UINT32 * Response)50 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
51 OUT UINT32 *MostRecentRequest,
52 OUT UINT32 *Response
53 )
54 {
55 EFI_STATUS Status;
56 UINTN DataSize;
57 EFI_TCG2_PHYSICAL_PRESENCE PpData;
58
59 DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
60
61 //
62 // Get the Physical Presence variable
63 //
64 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
65 Status = mTcg2PpSmmVariable->SmmGetVariable (
66 TCG2_PHYSICAL_PRESENCE_VARIABLE,
67 &gEfiTcg2PhysicalPresenceGuid,
68 NULL,
69 &DataSize,
70 &PpData
71 );
72 if (EFI_ERROR (Status)) {
73 *MostRecentRequest = 0;
74 *Response = 0;
75 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
76 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
77 }
78
79 *MostRecentRequest = PpData.LastPPRequest;
80 *Response = PpData.PPResponse;
81
82 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
83 }
84
85 /**
86 The handler for TPM physical presence function:
87 Submit TPM Operation Request to Pre-OS Environment and
88 Submit TPM Operation Request to Pre-OS Environment 2.
89
90 This API should be invoked in OS runtime phase to interface with ACPI method.
91
92 Caution: This function may receive untrusted input.
93
94 @param[in, out] Pointer to OperationRequest TPM physical presence operation request.
95 @param[in, out] Pointer to RequestParameter TPM physical presence operation request parameter.
96
97 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
98 Submit TPM Operation Request to Pre-OS Environment 2.
99 **/
100 UINT32
Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(IN OUT UINT32 * OperationRequest,IN OUT UINT32 * RequestParameter)101 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
102 IN OUT UINT32 *OperationRequest,
103 IN OUT UINT32 *RequestParameter
104 )
105 {
106 EFI_STATUS Status;
107 UINT32 ReturnCode;
108 UINTN DataSize;
109 EFI_TCG2_PHYSICAL_PRESENCE PpData;
110 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
111
112 DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", *OperationRequest, *RequestParameter));
113 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
114
115 //
116 // Get the Physical Presence variable
117 //
118 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
119 Status = mTcg2PpSmmVariable->SmmGetVariable (
120 TCG2_PHYSICAL_PRESENCE_VARIABLE,
121 &gEfiTcg2PhysicalPresenceGuid,
122 NULL,
123 &DataSize,
124 &PpData
125 );
126 if (EFI_ERROR (Status)) {
127 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
128 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
129 goto EXIT;
130 }
131
132 if ((*OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
133 (*OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
134 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
135 goto EXIT;
136 }
137
138 if ((PpData.PPRequest != *OperationRequest) ||
139 (PpData.PPRequestParameter != *RequestParameter)) {
140 PpData.PPRequest = (UINT8)*OperationRequest;
141 PpData.PPRequestParameter = *RequestParameter;
142 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
143 Status = mTcg2PpSmmVariable->SmmSetVariable (
144 TCG2_PHYSICAL_PRESENCE_VARIABLE,
145 &gEfiTcg2PhysicalPresenceGuid,
146 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
147 DataSize,
148 &PpData
149 );
150 if (EFI_ERROR (Status)) {
151 DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
152 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
153 goto EXIT;
154 }
155 }
156
157 if (*OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
158 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
159 Status = mTcg2PpSmmVariable->SmmGetVariable (
160 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
161 &gEfiTcg2PhysicalPresenceGuid,
162 NULL,
163 &DataSize,
164 &Flags
165 );
166 if (EFI_ERROR (Status)) {
167 Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
168 }
169 ReturnCode = Tcg2PpVendorLibSubmitRequestToPreOSFunction (*OperationRequest, Flags.PPFlags, *RequestParameter);
170 }
171
172 EXIT:
173 //
174 // Sync PPRQ/PPRM from PP Variable if PP submission fails
175 //
176 if (ReturnCode != TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
177 DEBUG ((EFI_D_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));
178 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
179 ZeroMem(&PpData, DataSize);
180 Status = mTcg2PpSmmVariable->SmmGetVariable (
181 TCG2_PHYSICAL_PRESENCE_VARIABLE,
182 &gEfiTcg2PhysicalPresenceGuid,
183 NULL,
184 &DataSize,
185 &PpData
186 );
187 *OperationRequest = (UINT32)PpData.PPRequest;
188 *RequestParameter = PpData.PPRequestParameter;
189 }
190
191 return ReturnCode;
192 }
193
194 /**
195 The handler for TPM physical presence function:
196 Submit TPM Operation Request to Pre-OS Environment and
197 Submit TPM Operation Request to Pre-OS Environment 2.
198
199 This API should be invoked in OS runtime phase to interface with ACPI method.
200
201 Caution: This function may receive untrusted input.
202
203 @param[in] OperationRequest TPM physical presence operation request.
204 @param[in] RequestParameter TPM physical presence operation request parameter.
205
206 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
207 Submit TPM Operation Request to Pre-OS Environment 2.
208 **/
209 UINT32
210 EFIAPI
Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction(IN UINT32 OperationRequest,IN UINT32 RequestParameter)211 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
212 IN UINT32 OperationRequest,
213 IN UINT32 RequestParameter
214 )
215 {
216 UINT32 TempOperationRequest;
217 UINT32 TempRequestParameter;
218
219 TempOperationRequest = OperationRequest;
220 TempRequestParameter = RequestParameter;
221
222 return Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(&TempOperationRequest, &TempRequestParameter);
223 }
224
225 /**
226 The handler for TPM physical presence function:
227 Get User Confirmation Status for Operation.
228
229 This API should be invoked in OS runtime phase to interface with ACPI method.
230
231 Caution: This function may receive untrusted input.
232
233 @param[in] OperationRequest TPM physical presence operation request.
234
235 @return Return Code for Get User Confirmation Status for Operation.
236 **/
237 UINT32
238 EFIAPI
Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction(IN UINT32 OperationRequest)239 Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
240 IN UINT32 OperationRequest
241 )
242 {
243 EFI_STATUS Status;
244 UINTN DataSize;
245 EFI_TCG2_PHYSICAL_PRESENCE PpData;
246 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
247 BOOLEAN RequestConfirmed;
248
249 DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
250
251 //
252 // Get the Physical Presence variable
253 //
254 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
255 Status = mTcg2PpSmmVariable->SmmGetVariable (
256 TCG2_PHYSICAL_PRESENCE_VARIABLE,
257 &gEfiTcg2PhysicalPresenceGuid,
258 NULL,
259 &DataSize,
260 &PpData
261 );
262 if (EFI_ERROR (Status)) {
263 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
264 return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
265 }
266 //
267 // Get the Physical Presence flags
268 //
269 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
270 Status = mTcg2PpSmmVariable->SmmGetVariable (
271 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
272 &gEfiTcg2PhysicalPresenceGuid,
273 NULL,
274 &DataSize,
275 &Flags
276 );
277 if (EFI_ERROR (Status)) {
278 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
279 return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
280 }
281
282 RequestConfirmed = FALSE;
283
284 switch (OperationRequest) {
285 case TCG2_PHYSICAL_PRESENCE_CLEAR:
286 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
287 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
288 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
289 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
290 RequestConfirmed = TRUE;
291 }
292 break;
293
294 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
295 RequestConfirmed = TRUE;
296 break;
297
298 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
299 break;
300
301 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
302 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
303 RequestConfirmed = TRUE;
304 }
305 break;
306
307 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
308 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
309 RequestConfirmed = TRUE;
310 }
311 break;
312
313 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
314 RequestConfirmed = TRUE;
315 break;
316
317 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
318 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
319 RequestConfirmed = TRUE;
320 }
321 break;
322
323 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
324 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
325 RequestConfirmed = TRUE;
326 }
327 break;
328
329 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
330 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
331 RequestConfirmed = TRUE;
332 break;
333
334 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
335 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
336 break;
337
338 default:
339 if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
340 RequestConfirmed = TRUE;
341 } else {
342 if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
343 return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
344 }
345 }
346 break;
347 }
348
349 if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
350 return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
351 }
352
353 if (RequestConfirmed) {
354 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
355 } else {
356 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
357 }
358 }
359
360 /**
361 The constructor function locates SmmVariable protocol.
362
363 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
364
365 @param ImageHandle The firmware allocated handle for the EFI image.
366 @param SystemTable A pointer to the EFI System Table.
367
368 @retval EFI_SUCCESS The constructor successfully added string package.
369 @retval Other value The constructor can't add string package.
370 **/
371 EFI_STATUS
372 EFIAPI
Tcg2PhysicalPresenceLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)373 Tcg2PhysicalPresenceLibConstructor (
374 IN EFI_HANDLE ImageHandle,
375 IN EFI_SYSTEM_TABLE *SystemTable
376 )
377 {
378 EFI_STATUS Status;
379
380 //
381 // Locate SmmVariableProtocol.
382 //
383 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
384 ASSERT_EFI_ERROR (Status);
385
386 return EFI_SUCCESS;
387 }
388