1 /** @file
2   Implement TPM2 Hierarchy related command.
3 
4 Copyright (c) 2013 - 2014, 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 
15 #include <IndustryStandard/UefiTcgPlatform.h>
16 #include <Library/Tpm2CommandLib.h>
17 #include <Library/Tpm2DeviceLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 
22 #pragma pack(1)
23 
24 typedef struct {
25   TPM2_COMMAND_HEADER       Header;
26   TPMI_RH_HIERARCHY_AUTH    AuthHandle;
27   UINT32                    AuthSessionSize;
28   TPMS_AUTH_COMMAND         AuthSession;
29   TPM2B_DIGEST              AuthPolicy;
30   TPMI_ALG_HASH             HashAlg;
31 } TPM2_SET_PRIMARY_POLICY_COMMAND;
32 
33 typedef struct {
34   TPM2_RESPONSE_HEADER       Header;
35   UINT32                     AuthSessionSize;
36   TPMS_AUTH_RESPONSE         AuthSession;
37 } TPM2_SET_PRIMARY_POLICY_RESPONSE;
38 
39 typedef struct {
40   TPM2_COMMAND_HEADER       Header;
41   TPMI_RH_CLEAR             AuthHandle;
42   UINT32                    AuthorizationSize;
43   TPMS_AUTH_COMMAND         AuthSession;
44 } TPM2_CLEAR_COMMAND;
45 
46 typedef struct {
47   TPM2_RESPONSE_HEADER       Header;
48   UINT32                     ParameterSize;
49   TPMS_AUTH_RESPONSE         AuthSession;
50 } TPM2_CLEAR_RESPONSE;
51 
52 typedef struct {
53   TPM2_COMMAND_HEADER       Header;
54   TPMI_RH_CLEAR             AuthHandle;
55   UINT32                    AuthorizationSize;
56   TPMS_AUTH_COMMAND         AuthSession;
57   TPMI_YES_NO               Disable;
58 } TPM2_CLEAR_CONTROL_COMMAND;
59 
60 typedef struct {
61   TPM2_RESPONSE_HEADER       Header;
62   UINT32                     ParameterSize;
63   TPMS_AUTH_RESPONSE         AuthSession;
64 } TPM2_CLEAR_CONTROL_RESPONSE;
65 
66 typedef struct {
67   TPM2_COMMAND_HEADER       Header;
68   TPMI_RH_HIERARCHY_AUTH    AuthHandle;
69   UINT32                    AuthorizationSize;
70   TPMS_AUTH_COMMAND         AuthSession;
71   TPM2B_AUTH                NewAuth;
72 } TPM2_HIERARCHY_CHANGE_AUTH_COMMAND;
73 
74 typedef struct {
75   TPM2_RESPONSE_HEADER       Header;
76   UINT32                     ParameterSize;
77   TPMS_AUTH_RESPONSE         AuthSession;
78 } TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE;
79 
80 typedef struct {
81   TPM2_COMMAND_HEADER       Header;
82   TPMI_RH_PLATFORM          AuthHandle;
83   UINT32                    AuthorizationSize;
84   TPMS_AUTH_COMMAND         AuthSession;
85 } TPM2_CHANGE_EPS_COMMAND;
86 
87 typedef struct {
88   TPM2_RESPONSE_HEADER       Header;
89   UINT32                     ParameterSize;
90   TPMS_AUTH_RESPONSE         AuthSession;
91 } TPM2_CHANGE_EPS_RESPONSE;
92 
93 typedef struct {
94   TPM2_COMMAND_HEADER       Header;
95   TPMI_RH_PLATFORM          AuthHandle;
96   UINT32                    AuthorizationSize;
97   TPMS_AUTH_COMMAND         AuthSession;
98 } TPM2_CHANGE_PPS_COMMAND;
99 
100 typedef struct {
101   TPM2_RESPONSE_HEADER       Header;
102   UINT32                     ParameterSize;
103   TPMS_AUTH_RESPONSE         AuthSession;
104 } TPM2_CHANGE_PPS_RESPONSE;
105 
106 typedef struct {
107   TPM2_COMMAND_HEADER       Header;
108   TPMI_RH_HIERARCHY         AuthHandle;
109   UINT32                    AuthorizationSize;
110   TPMS_AUTH_COMMAND         AuthSession;
111   TPMI_RH_HIERARCHY         Hierarchy;
112   TPMI_YES_NO               State;
113 } TPM2_HIERARCHY_CONTROL_COMMAND;
114 
115 typedef struct {
116   TPM2_RESPONSE_HEADER       Header;
117   UINT32                     ParameterSize;
118   TPMS_AUTH_RESPONSE         AuthSession;
119 } TPM2_HIERARCHY_CONTROL_RESPONSE;
120 
121 #pragma pack()
122 
123 /**
124   This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the
125   storage hierarchy (ownerPolicy), and and the endorsement hierarchy (endorsementPolicy).
126 
127   @param[in]  AuthHandle            TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} parameters to be validated
128   @param[in]  AuthSession           Auth Session context
129   @param[in]  AuthPolicy            An authorization policy hash
130   @param[in]  HashAlg               The hash algorithm to use for the policy
131 
132   @retval EFI_SUCCESS      Operation completed successfully.
133   @retval EFI_DEVICE_ERROR Unexpected device behavior.
134 **/
135 EFI_STATUS
136 EFIAPI
Tpm2SetPrimaryPolicy(IN TPMI_RH_HIERARCHY_AUTH AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession,IN TPM2B_DIGEST * AuthPolicy,IN TPMI_ALG_HASH HashAlg)137 Tpm2SetPrimaryPolicy (
138   IN  TPMI_RH_HIERARCHY_AUTH    AuthHandle,
139   IN  TPMS_AUTH_COMMAND         *AuthSession,
140   IN  TPM2B_DIGEST              *AuthPolicy,
141   IN  TPMI_ALG_HASH             HashAlg
142   )
143 {
144   EFI_STATUS                                 Status;
145   TPM2_SET_PRIMARY_POLICY_COMMAND            SendBuffer;
146   TPM2_SET_PRIMARY_POLICY_RESPONSE           RecvBuffer;
147   UINT32                                     SendBufferSize;
148   UINT32                                     RecvBufferSize;
149   UINT8                                      *Buffer;
150   UINT32                                     SessionInfoSize;
151 
152   //
153   // Construct command
154   //
155   SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
156   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetPrimaryPolicy);
157 
158   SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
159 
160   //
161   // Add in Auth session
162   //
163   Buffer = (UINT8 *)&SendBuffer.AuthSession;
164 
165   // sessionInfoSize
166   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
167   Buffer += SessionInfoSize;
168   SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
169 
170   //
171   // Real data
172   //
173   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(AuthPolicy->size));
174   Buffer += sizeof(UINT16);
175   CopyMem (Buffer, AuthPolicy->buffer, AuthPolicy->size);
176   Buffer += AuthPolicy->size;
177   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));
178   Buffer += sizeof(UINT16);
179 
180   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
181   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
182 
183   //
184   // send Tpm command
185   //
186   RecvBufferSize = sizeof (RecvBuffer);
187   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
188   if (EFI_ERROR (Status)) {
189     return Status;
190   }
191 
192   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
193     DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize));
194     return EFI_DEVICE_ERROR;
195   }
196   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
197     DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
198     return EFI_DEVICE_ERROR;
199   }
200 
201   return EFI_SUCCESS;
202 }
203 
204 /**
205   This command removes all TPM context associated with a specific Owner.
206 
207   @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
208   @param[in] AuthSession       Auth Session context
209 
210   @retval EFI_SUCCESS      Operation completed successfully.
211   @retval EFI_DEVICE_ERROR Unexpected device behavior.
212 **/
213 EFI_STATUS
214 EFIAPI
Tpm2Clear(IN TPMI_RH_CLEAR AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession OPTIONAL)215 Tpm2Clear (
216   IN TPMI_RH_CLEAR             AuthHandle,
217   IN TPMS_AUTH_COMMAND         *AuthSession OPTIONAL
218   )
219 {
220   EFI_STATUS                        Status;
221   TPM2_CLEAR_COMMAND                Cmd;
222   TPM2_CLEAR_RESPONSE               Res;
223   UINT32                            ResultBufSize;
224   UINT32                            CmdSize;
225   UINT32                            RespSize;
226   UINT8                             *Buffer;
227   UINT32                            SessionInfoSize;
228 
229   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
230   Cmd.Header.commandCode = SwapBytes32(TPM_CC_Clear);
231   Cmd.AuthHandle         = SwapBytes32(AuthHandle);
232 
233   //
234   // Add in Auth session
235   //
236   Buffer = (UINT8 *)&Cmd.AuthSession;
237 
238   // sessionInfoSize
239   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
240   Buffer += SessionInfoSize;
241   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
242 
243   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
244   Cmd.Header.paramSize   = SwapBytes32(CmdSize);
245 
246   ResultBufSize = sizeof(Res);
247   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
248   if (EFI_ERROR(Status)) {
249     return Status;
250   }
251 
252   if (ResultBufSize > sizeof(Res)) {
253     DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n"));
254     return EFI_BUFFER_TOO_SMALL;
255   }
256 
257   //
258   // Validate response headers
259   //
260   RespSize = SwapBytes32(Res.Header.paramSize);
261   if (RespSize > sizeof(Res)) {
262     DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize));
263     return EFI_BUFFER_TOO_SMALL;
264   }
265 
266   //
267   // Fail if command failed
268   //
269   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
270     DEBUG ((EFI_D_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
271     return EFI_DEVICE_ERROR;
272   }
273 
274   //
275   // Unmarshal the response
276   //
277 
278   // None
279 
280   return EFI_SUCCESS;
281 }
282 
283 /**
284   Disables and enables the execution of TPM2_Clear().
285 
286   @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
287   @param[in] AuthSession       Auth Session context
288   @param[in] Disable           YES if the disableOwnerClear flag is to be SET,
289                                NO if the flag is to be CLEAR.
290 
291   @retval EFI_SUCCESS      Operation completed successfully.
292   @retval EFI_DEVICE_ERROR Unexpected device behavior.
293 **/
294 EFI_STATUS
295 EFIAPI
Tpm2ClearControl(IN TPMI_RH_CLEAR AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession,OPTIONAL IN TPMI_YES_NO Disable)296 Tpm2ClearControl (
297   IN TPMI_RH_CLEAR             AuthHandle,
298   IN TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL
299   IN TPMI_YES_NO               Disable
300   )
301 {
302   EFI_STATUS                        Status;
303   TPM2_CLEAR_CONTROL_COMMAND        Cmd;
304   TPM2_CLEAR_CONTROL_RESPONSE       Res;
305   UINT32                            ResultBufSize;
306   UINT32                            CmdSize;
307   UINT32                            RespSize;
308   UINT8                             *Buffer;
309   UINT32                            SessionInfoSize;
310 
311   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
312   Cmd.Header.commandCode = SwapBytes32(TPM_CC_ClearControl);
313   Cmd.AuthHandle         = SwapBytes32(AuthHandle);
314 
315   //
316   // Add in Auth session
317   //
318   Buffer = (UINT8 *)&Cmd.AuthSession;
319 
320   // sessionInfoSize
321   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
322   Buffer += SessionInfoSize;
323   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
324 
325   // disable
326   *(UINT8 *)Buffer = Disable;
327   Buffer++;
328 
329   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
330   Cmd.Header.paramSize   = SwapBytes32(CmdSize);
331 
332   ResultBufSize = sizeof(Res);
333   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
334   if (EFI_ERROR(Status)) {
335     return Status;
336   }
337 
338   if (ResultBufSize > sizeof(Res)) {
339     DEBUG ((EFI_D_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n"));
340     return EFI_BUFFER_TOO_SMALL;
341   }
342 
343   //
344   // Validate response headers
345   //
346   RespSize = SwapBytes32(Res.Header.paramSize);
347   if (RespSize > sizeof(Res)) {
348     DEBUG ((EFI_D_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize));
349     return EFI_BUFFER_TOO_SMALL;
350   }
351 
352   //
353   // Fail if command failed
354   //
355   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
356     DEBUG ((EFI_D_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
357     return EFI_DEVICE_ERROR;
358   }
359 
360   //
361   // Unmarshal the response
362   //
363 
364   // None
365 
366   return EFI_SUCCESS;
367 }
368 
369 /**
370   This command allows the authorization secret for a hierarchy or lockout to be changed using the current
371   authorization value as the command authorization.
372 
373   @param[in] AuthHandle        TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
374   @param[in] AuthSession       Auth Session context
375   @param[in] NewAuth           New authorization secret
376 
377   @retval EFI_SUCCESS      Operation completed successfully.
378   @retval EFI_DEVICE_ERROR Unexpected device behavior.
379 **/
380 EFI_STATUS
381 EFIAPI
Tpm2HierarchyChangeAuth(IN TPMI_RH_HIERARCHY_AUTH AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession,IN TPM2B_AUTH * NewAuth)382 Tpm2HierarchyChangeAuth (
383   IN TPMI_RH_HIERARCHY_AUTH    AuthHandle,
384   IN TPMS_AUTH_COMMAND         *AuthSession,
385   IN TPM2B_AUTH                *NewAuth
386   )
387 {
388   EFI_STATUS                           Status;
389   TPM2_HIERARCHY_CHANGE_AUTH_COMMAND   Cmd;
390   TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE  Res;
391   UINT32                               CmdSize;
392   UINT32                               RespSize;
393   UINT8                                *Buffer;
394   UINT32                               SessionInfoSize;
395   UINT8                                *ResultBuf;
396   UINT32                               ResultBufSize;
397 
398   //
399   // Construct command
400   //
401   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
402   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
403   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyChangeAuth);
404   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
405 
406   //
407   // Add in Auth session
408   //
409   Buffer = (UINT8 *)&Cmd.AuthSession;
410 
411   // sessionInfoSize
412   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
413   Buffer += SessionInfoSize;
414   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
415 
416   // New Authorization size
417   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NewAuth->size));
418   Buffer += sizeof(UINT16);
419 
420   // New Authorizeation
421   CopyMem(Buffer, NewAuth->buffer, NewAuth->size);
422   Buffer += NewAuth->size;
423 
424   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
425   Cmd.Header.paramSize = SwapBytes32(CmdSize);
426 
427   ResultBuf     = (UINT8 *) &Res;
428   ResultBufSize = sizeof(Res);
429 
430   //
431   // Call the TPM
432   //
433   Status = Tpm2SubmitCommand (
434              CmdSize,
435              (UINT8 *)&Cmd,
436              &ResultBufSize,
437              ResultBuf
438              );
439 
440   if (ResultBufSize > sizeof(Res)) {
441     DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n"));
442     return EFI_BUFFER_TOO_SMALL;
443   }
444 
445   //
446   // Validate response headers
447   //
448   RespSize = SwapBytes32(Res.Header.paramSize);
449   if (RespSize > sizeof(Res)) {
450     DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize));
451     return EFI_BUFFER_TOO_SMALL;
452   }
453 
454   //
455   // Fail if command failed
456   //
457   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
458     DEBUG((EFI_D_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
459     return EFI_DEVICE_ERROR;
460   }
461 
462   return EFI_SUCCESS;
463 }
464 
465 /**
466   This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to
467   their default initialization values.
468 
469   @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}
470   @param[in] AuthSession       Auth Session context
471 
472   @retval EFI_SUCCESS      Operation completed successfully.
473   @retval EFI_DEVICE_ERROR Unexpected device behavior.
474 **/
475 EFI_STATUS
476 EFIAPI
Tpm2ChangeEPS(IN TPMI_RH_PLATFORM AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession)477 Tpm2ChangeEPS (
478   IN TPMI_RH_PLATFORM          AuthHandle,
479   IN TPMS_AUTH_COMMAND         *AuthSession
480   )
481 {
482   EFI_STATUS                Status;
483   TPM2_CHANGE_EPS_COMMAND   Cmd;
484   TPM2_CHANGE_EPS_RESPONSE  Res;
485   UINT32                    CmdSize;
486   UINT32                    RespSize;
487   UINT8                     *Buffer;
488   UINT32                    SessionInfoSize;
489   UINT8                     *ResultBuf;
490   UINT32                    ResultBufSize;
491 
492   //
493   // Construct command
494   //
495   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
496   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
497   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangeEPS);
498   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
499 
500   //
501   // Add in Auth session
502   //
503   Buffer = (UINT8 *)&Cmd.AuthSession;
504 
505   // sessionInfoSize
506   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
507   Buffer += SessionInfoSize;
508   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
509 
510   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
511   Cmd.Header.paramSize = SwapBytes32(CmdSize);
512 
513   ResultBuf     = (UINT8 *) &Res;
514   ResultBufSize = sizeof(Res);
515 
516   //
517   // Call the TPM
518   //
519   Status = Tpm2SubmitCommand (
520              CmdSize,
521              (UINT8 *)&Cmd,
522              &ResultBufSize,
523              ResultBuf
524              );
525 
526   if (ResultBufSize > sizeof(Res)) {
527     DEBUG ((EFI_D_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n"));
528     return EFI_BUFFER_TOO_SMALL;
529   }
530 
531   //
532   // Validate response headers
533   //
534   RespSize = SwapBytes32(Res.Header.paramSize);
535   if (RespSize > sizeof(Res)) {
536     DEBUG ((EFI_D_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize));
537     return EFI_BUFFER_TOO_SMALL;
538   }
539 
540   //
541   // Fail if command failed
542   //
543   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
544     DEBUG((EFI_D_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
545     return EFI_DEVICE_ERROR;
546   }
547 
548   return EFI_SUCCESS;
549 }
550 
551 /**
552   This replaces the current PPS with a value from the RNG and sets platformPolicy to the default
553   initialization value (the Empty Buffer).
554 
555   @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}
556   @param[in] AuthSession       Auth Session context
557 
558   @retval EFI_SUCCESS      Operation completed successfully.
559   @retval EFI_DEVICE_ERROR Unexpected device behavior.
560 **/
561 EFI_STATUS
562 EFIAPI
Tpm2ChangePPS(IN TPMI_RH_PLATFORM AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession)563 Tpm2ChangePPS (
564   IN TPMI_RH_PLATFORM          AuthHandle,
565   IN TPMS_AUTH_COMMAND         *AuthSession
566   )
567 {
568   EFI_STATUS                Status;
569   TPM2_CHANGE_PPS_COMMAND   Cmd;
570   TPM2_CHANGE_PPS_RESPONSE  Res;
571   UINT32                    CmdSize;
572   UINT32                    RespSize;
573   UINT8                     *Buffer;
574   UINT32                    SessionInfoSize;
575   UINT8                     *ResultBuf;
576   UINT32                    ResultBufSize;
577 
578   //
579   // Construct command
580   //
581   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
582   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
583   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangePPS);
584   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
585 
586   //
587   // Add in Auth session
588   //
589   Buffer = (UINT8 *)&Cmd.AuthSession;
590 
591   // sessionInfoSize
592   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
593   Buffer += SessionInfoSize;
594   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
595 
596   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
597   Cmd.Header.paramSize = SwapBytes32(CmdSize);
598 
599   ResultBuf     = (UINT8 *) &Res;
600   ResultBufSize = sizeof(Res);
601 
602   //
603   // Call the TPM
604   //
605   Status = Tpm2SubmitCommand (
606              CmdSize,
607              (UINT8 *)&Cmd,
608              &ResultBufSize,
609              ResultBuf
610              );
611 
612   if (ResultBufSize > sizeof(Res)) {
613     DEBUG ((EFI_D_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n"));
614     return EFI_BUFFER_TOO_SMALL;
615   }
616 
617   //
618   // Validate response headers
619   //
620   RespSize = SwapBytes32(Res.Header.paramSize);
621   if (RespSize > sizeof(Res)) {
622     DEBUG ((EFI_D_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize));
623     return EFI_BUFFER_TOO_SMALL;
624   }
625 
626   //
627   // Fail if command failed
628   //
629   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
630     DEBUG((EFI_D_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
631     return EFI_DEVICE_ERROR;
632   }
633 
634   return EFI_SUCCESS;
635 }
636 
637 /**
638   This command enables and disables use of a hierarchy.
639 
640   @param[in] AuthHandle        TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
641   @param[in] AuthSession       Auth Session context
642   @param[in] Hierarchy         Hierarchy of the enable being modified
643   @param[in] State             YES if the enable should be SET,
644                                NO if the enable should be CLEAR
645 
646   @retval EFI_SUCCESS      Operation completed successfully.
647   @retval EFI_DEVICE_ERROR Unexpected device behavior.
648 **/
649 EFI_STATUS
650 EFIAPI
Tpm2HierarchyControl(IN TPMI_RH_HIERARCHY AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession,IN TPMI_RH_HIERARCHY Hierarchy,IN TPMI_YES_NO State)651 Tpm2HierarchyControl (
652   IN TPMI_RH_HIERARCHY         AuthHandle,
653   IN TPMS_AUTH_COMMAND         *AuthSession,
654   IN TPMI_RH_HIERARCHY         Hierarchy,
655   IN TPMI_YES_NO               State
656   )
657 {
658   EFI_STATUS                       Status;
659   TPM2_HIERARCHY_CONTROL_COMMAND   Cmd;
660   TPM2_HIERARCHY_CONTROL_RESPONSE  Res;
661   UINT32                           CmdSize;
662   UINT32                           RespSize;
663   UINT8                            *Buffer;
664   UINT32                           SessionInfoSize;
665   UINT8                            *ResultBuf;
666   UINT32                           ResultBufSize;
667 
668   //
669   // Construct command
670   //
671   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
672   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
673   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyControl);
674   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
675 
676   //
677   // Add in Auth session
678   //
679   Buffer = (UINT8 *)&Cmd.AuthSession;
680 
681   // sessionInfoSize
682   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
683   Buffer += SessionInfoSize;
684   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
685 
686   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Hierarchy));
687   Buffer += sizeof(UINT32);
688 
689   *(UINT8 *)Buffer = State;
690   Buffer++;
691 
692   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
693   Cmd.Header.paramSize = SwapBytes32(CmdSize);
694 
695   ResultBuf     = (UINT8 *) &Res;
696   ResultBufSize = sizeof(Res);
697 
698   //
699   // Call the TPM
700   //
701   Status = Tpm2SubmitCommand (
702              CmdSize,
703              (UINT8 *)&Cmd,
704              &ResultBufSize,
705              ResultBuf
706              );
707 
708   if (ResultBufSize > sizeof(Res)) {
709     DEBUG ((EFI_D_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n"));
710     return EFI_BUFFER_TOO_SMALL;
711   }
712 
713   //
714   // Validate response headers
715   //
716   RespSize = SwapBytes32(Res.Header.paramSize);
717   if (RespSize > sizeof(Res)) {
718     DEBUG ((EFI_D_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize));
719     return EFI_BUFFER_TOO_SMALL;
720   }
721 
722   //
723   // Fail if command failed
724   //
725   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
726     DEBUG((EFI_D_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
727     return EFI_DEVICE_ERROR;
728   }
729 
730   return EFI_SUCCESS;
731 }
732