]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c
SecurityPkg: Support PP version lower than 1.3
[mirror_edk2.git] / SecurityPkg / Library / SmmTcg2PhysicalPresenceLib / SmmTcg2PhysicalPresenceLib.c
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 - 2018, 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/BaseLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/BaseMemoryLib.h>
33 #include <Library/Tcg2PpVendorLib.h>
34 #include <Library/SmmServicesTableLib.h>
35
36 #define PP_INF_VERSION_1_2 "1.2"
37
38 EFI_SMM_VARIABLE_PROTOCOL *mTcg2PpSmmVariable;
39 BOOLEAN mIsTcg2PPVerLowerThan_1_3 = FALSE;
40
41 /**
42 The handler for TPM physical presence function:
43 Return TPM Operation Response to OS Environment.
44
45 This API should be invoked in OS runtime phase to interface with ACPI method.
46
47 @param[out] MostRecentRequest Most recent operation request.
48 @param[out] Response Response to the most recent operation request.
49
50 @return Return Code for Return TPM Operation Response to OS Environment.
51 **/
52 UINT32
53 EFIAPI
54 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
55 OUT UINT32 *MostRecentRequest,
56 OUT UINT32 *Response
57 )
58 {
59 EFI_STATUS Status;
60 UINTN DataSize;
61 EFI_TCG2_PHYSICAL_PRESENCE PpData;
62
63 DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
64
65 //
66 // Get the Physical Presence variable
67 //
68 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
69 Status = mTcg2PpSmmVariable->SmmGetVariable (
70 TCG2_PHYSICAL_PRESENCE_VARIABLE,
71 &gEfiTcg2PhysicalPresenceGuid,
72 NULL,
73 &DataSize,
74 &PpData
75 );
76 if (EFI_ERROR (Status)) {
77 *MostRecentRequest = 0;
78 *Response = 0;
79 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
80 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
81 }
82
83 *MostRecentRequest = PpData.LastPPRequest;
84 *Response = PpData.PPResponse;
85
86 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
87 }
88
89 /**
90 The handler for TPM physical presence function:
91 Submit TPM Operation Request to Pre-OS Environment and
92 Submit TPM Operation Request to Pre-OS Environment 2.
93
94 This API should be invoked in OS runtime phase to interface with ACPI method.
95
96 Caution: This function may receive untrusted input.
97
98 @param[in, out] Pointer to OperationRequest TPM physical presence operation request.
99 @param[in, out] Pointer to RequestParameter TPM physical presence operation request parameter.
100
101 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
102 Submit TPM Operation Request to Pre-OS Environment 2.
103 **/
104 UINT32
105 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
106 IN OUT UINT32 *OperationRequest,
107 IN OUT UINT32 *RequestParameter
108 )
109 {
110 EFI_STATUS Status;
111 UINT32 ReturnCode;
112 UINTN DataSize;
113 EFI_TCG2_PHYSICAL_PRESENCE PpData;
114 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
115
116 DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", *OperationRequest, *RequestParameter));
117 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
118
119 //
120 // Get the Physical Presence variable
121 //
122 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
123 Status = mTcg2PpSmmVariable->SmmGetVariable (
124 TCG2_PHYSICAL_PRESENCE_VARIABLE,
125 &gEfiTcg2PhysicalPresenceGuid,
126 NULL,
127 &DataSize,
128 &PpData
129 );
130 if (EFI_ERROR (Status)) {
131 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
132 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
133 goto EXIT;
134 }
135
136 if ((*OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
137 (*OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
138 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
139 goto EXIT;
140 }
141
142 if ((PpData.PPRequest != *OperationRequest) ||
143 (PpData.PPRequestParameter != *RequestParameter)) {
144 PpData.PPRequest = (UINT8)*OperationRequest;
145 PpData.PPRequestParameter = *RequestParameter;
146 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
147 Status = mTcg2PpSmmVariable->SmmSetVariable (
148 TCG2_PHYSICAL_PRESENCE_VARIABLE,
149 &gEfiTcg2PhysicalPresenceGuid,
150 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
151 DataSize,
152 &PpData
153 );
154 if (EFI_ERROR (Status)) {
155 DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
156 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
157 goto EXIT;
158 }
159 }
160
161 if (*OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
162 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
163 Status = mTcg2PpSmmVariable->SmmGetVariable (
164 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
165 &gEfiTcg2PhysicalPresenceGuid,
166 NULL,
167 &DataSize,
168 &Flags
169 );
170 if (EFI_ERROR (Status)) {
171 Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
172 }
173 ReturnCode = Tcg2PpVendorLibSubmitRequestToPreOSFunction (*OperationRequest, Flags.PPFlags, *RequestParameter);
174 }
175
176 EXIT:
177 //
178 // Sync PPRQ/PPRM from PP Variable if PP submission fails
179 //
180 if (ReturnCode != TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
181 DEBUG ((EFI_D_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));
182 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
183 ZeroMem(&PpData, DataSize);
184 Status = mTcg2PpSmmVariable->SmmGetVariable (
185 TCG2_PHYSICAL_PRESENCE_VARIABLE,
186 &gEfiTcg2PhysicalPresenceGuid,
187 NULL,
188 &DataSize,
189 &PpData
190 );
191 *OperationRequest = (UINT32)PpData.PPRequest;
192 *RequestParameter = PpData.PPRequestParameter;
193 }
194
195 return ReturnCode;
196 }
197
198 /**
199 The handler for TPM physical presence function:
200 Submit TPM Operation Request to Pre-OS Environment and
201 Submit TPM Operation Request to Pre-OS Environment 2.
202
203 This API should be invoked in OS runtime phase to interface with ACPI method.
204
205 Caution: This function may receive untrusted input.
206
207 @param[in] OperationRequest TPM physical presence operation request.
208 @param[in] RequestParameter TPM physical presence operation request parameter.
209
210 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
211 Submit TPM Operation Request to Pre-OS Environment 2.
212 **/
213 UINT32
214 EFIAPI
215 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
216 IN UINT32 OperationRequest,
217 IN UINT32 RequestParameter
218 )
219 {
220 UINT32 TempOperationRequest;
221 UINT32 TempRequestParameter;
222
223 TempOperationRequest = OperationRequest;
224 TempRequestParameter = RequestParameter;
225
226 return Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(&TempOperationRequest, &TempRequestParameter);
227 }
228
229 /**
230 The handler for TPM physical presence function:
231 Get User Confirmation Status for Operation.
232
233 This API should be invoked in OS runtime phase to interface with ACPI method.
234
235 Caution: This function may receive untrusted input.
236
237 @param[in] OperationRequest TPM physical presence operation request.
238
239 @return Return Code for Get User Confirmation Status for Operation.
240 **/
241 UINT32
242 EFIAPI
243 Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
244 IN UINT32 OperationRequest
245 )
246 {
247 EFI_STATUS Status;
248 UINTN DataSize;
249 EFI_TCG2_PHYSICAL_PRESENCE PpData;
250 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
251 BOOLEAN RequestConfirmed;
252
253 DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
254
255 //
256 // Get the Physical Presence variable
257 //
258 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
259 Status = mTcg2PpSmmVariable->SmmGetVariable (
260 TCG2_PHYSICAL_PRESENCE_VARIABLE,
261 &gEfiTcg2PhysicalPresenceGuid,
262 NULL,
263 &DataSize,
264 &PpData
265 );
266 if (EFI_ERROR (Status)) {
267 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
268 return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
269 }
270 //
271 // Get the Physical Presence flags
272 //
273 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
274 Status = mTcg2PpSmmVariable->SmmGetVariable (
275 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
276 &gEfiTcg2PhysicalPresenceGuid,
277 NULL,
278 &DataSize,
279 &Flags
280 );
281 if (EFI_ERROR (Status)) {
282 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
283 return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
284 }
285
286 RequestConfirmed = FALSE;
287
288 switch (OperationRequest) {
289 case TCG2_PHYSICAL_PRESENCE_CLEAR:
290 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
291 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
292 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
293 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
294 RequestConfirmed = TRUE;
295 }
296 break;
297
298 case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
299 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
300 RequestConfirmed = TRUE;
301 break;
302
303 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
304 break;
305
306 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
307 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
308 RequestConfirmed = TRUE;
309 }
310 break;
311
312 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
313 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
314 RequestConfirmed = TRUE;
315 }
316 break;
317
318 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
319 RequestConfirmed = TRUE;
320 break;
321
322 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
323 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
324 RequestConfirmed = TRUE;
325 }
326 break;
327
328 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
329 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
330 RequestConfirmed = TRUE;
331 }
332 break;
333
334 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
335 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
336 RequestConfirmed = TRUE;
337 break;
338
339 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
340 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
341 break;
342
343 default:
344 if (mIsTcg2PPVerLowerThan_1_3 == FALSE) {
345 if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
346 //
347 // TCG2 PP1.3 spec defined operations that are reserved or un-implemented
348 //
349 return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
350 }
351 } else {
352 //
353 // TCG PP lower than 1.3. (1.0, 1.1, 1.2)
354 //
355 if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
356 RequestConfirmed = TRUE;
357 } else if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
358 return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
359 }
360 }
361 break;
362 }
363
364 if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
365 return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
366 }
367
368 if (RequestConfirmed) {
369 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
370 } else {
371 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
372 }
373 }
374
375 /**
376 The constructor function locates SmmVariable protocol.
377
378 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
379
380 @param ImageHandle The firmware allocated handle for the EFI image.
381 @param SystemTable A pointer to the EFI System Table.
382
383 @retval EFI_SUCCESS The constructor successfully added string package.
384 @retval Other value The constructor can't add string package.
385 **/
386 EFI_STATUS
387 EFIAPI
388 Tcg2PhysicalPresenceLibConstructor (
389 IN EFI_HANDLE ImageHandle,
390 IN EFI_SYSTEM_TABLE *SystemTable
391 )
392 {
393 EFI_STATUS Status;
394
395 if (AsciiStrnCmp(PP_INF_VERSION_1_2, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer), sizeof(PP_INF_VERSION_1_2) - 1) <= 0) {
396 mIsTcg2PPVerLowerThan_1_3 = TRUE;
397 }
398
399 //
400 // Locate SmmVariableProtocol.
401 //
402 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
403 ASSERT_EFI_ERROR (Status);
404
405 return EFI_SUCCESS;
406 }