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