]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c
SecurityPkg: Tcg2: Fix TCG2 PP issues
[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 - 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
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
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_VENDOR_SPECIFIC_OPERATION) ) {
134 //
135 // This command requires UI to prompt user for Auth data.
136 //
137 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
138 goto EXIT;
139 }
140
141 if ((PpData.PPRequest != *OperationRequest) ||
142 (PpData.PPRequestParameter != *RequestParameter)) {
143 PpData.PPRequest = (UINT8)*OperationRequest;
144 PpData.PPRequestParameter = *RequestParameter;
145 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
146 Status = mTcg2PpSmmVariable->SmmSetVariable (
147 TCG2_PHYSICAL_PRESENCE_VARIABLE,
148 &gEfiTcg2PhysicalPresenceGuid,
149 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
150 DataSize,
151 &PpData
152 );
153 }
154
155 if (EFI_ERROR (Status)) {
156 DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
157 ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
158 goto EXIT;
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;
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_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
299 RequestConfirmed = TRUE;
300 break;
301
302 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
303 break;
304
305 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
306 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
307 RequestConfirmed = TRUE;
308 }
309 break;
310
311 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
312 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
313 RequestConfirmed = TRUE;
314 }
315 break;
316
317 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
318 RequestConfirmed = TRUE;
319 break;
320
321 default:
322 if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
323 RequestConfirmed = TRUE;
324 } else {
325 if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
326 return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
327 }
328 }
329 break;
330 }
331
332 if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
333 return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
334 }
335
336 if (RequestConfirmed) {
337 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
338 } else {
339 return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
340 }
341 }
342
343 /**
344 The constructor function register UNI strings into imageHandle.
345
346 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
347
348 @param ImageHandle The firmware allocated handle for the EFI image.
349 @param SystemTable A pointer to the EFI System Table.
350
351 @retval EFI_SUCCESS The constructor successfully added string package.
352 @retval Other value The constructor can't add string package.
353 **/
354 EFI_STATUS
355 EFIAPI
356 Tcg2PhysicalPresenceLibConstructor (
357 IN EFI_HANDLE ImageHandle,
358 IN EFI_SYSTEM_TABLE *SystemTable
359 )
360 {
361 EFI_STATUS Status;
362
363 //
364 // Locate SmmVariableProtocol.
365 //
366 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
367 ASSERT_EFI_ERROR (Status);
368
369 return EFI_SUCCESS;
370 }