This patch just moves function Tpm2CommandAllocPcr() from DxeTcg2PhysicalPresenceLib.c to Tpm2CommandLib as Tpm2PcrAllocateBanks() and no functionality change. Cc: Chao B Zhang <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
		
			
				
	
	
		
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implement TPM2 Integrity related command.
 | |
| 
 | |
| Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <IndustryStandard/UefiTcgPlatform.h>
 | |
| #include <Library/Tpm2CommandLib.h>
 | |
| #include <Library/Tpm2DeviceLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| 
 | |
| #pragma pack(1)
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_COMMAND_HEADER       Header;
 | |
|   TPMI_DH_PCR               PcrHandle;
 | |
|   UINT32                    AuthorizationSize;
 | |
|   TPMS_AUTH_COMMAND         AuthSessionPcr;
 | |
|   TPML_DIGEST_VALUES        DigestValues;
 | |
| } TPM2_PCR_EXTEND_COMMAND;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_RESPONSE_HEADER       Header;
 | |
|   UINT32                     ParameterSize;
 | |
|   TPMS_AUTH_RESPONSE         AuthSessionPcr;
 | |
| } TPM2_PCR_EXTEND_RESPONSE;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_COMMAND_HEADER       Header;
 | |
|   TPMI_DH_PCR               PcrHandle;
 | |
|   UINT32                    AuthorizationSize;
 | |
|   TPMS_AUTH_COMMAND         AuthSessionPcr;
 | |
|   TPM2B_EVENT               EventData;
 | |
| } TPM2_PCR_EVENT_COMMAND;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_RESPONSE_HEADER       Header;
 | |
|   UINT32                     ParameterSize;
 | |
|   TPML_DIGEST_VALUES         Digests;
 | |
|   TPMS_AUTH_RESPONSE         AuthSessionPcr;
 | |
| } TPM2_PCR_EVENT_RESPONSE;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_COMMAND_HEADER       Header;
 | |
|   TPML_PCR_SELECTION        PcrSelectionIn;
 | |
| } TPM2_PCR_READ_COMMAND;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_RESPONSE_HEADER      Header;
 | |
|   UINT32                    PcrUpdateCounter;
 | |
|   TPML_PCR_SELECTION        PcrSelectionOut;
 | |
|   TPML_DIGEST               PcrValues;
 | |
| } TPM2_PCR_READ_RESPONSE;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_COMMAND_HEADER       Header;
 | |
|   TPMI_RH_PLATFORM          AuthHandle;
 | |
|   UINT32                    AuthSessionSize;
 | |
|   TPMS_AUTH_COMMAND         AuthSession;
 | |
|   TPML_PCR_SELECTION        PcrAllocation;
 | |
| } TPM2_PCR_ALLOCATE_COMMAND;
 | |
| 
 | |
| typedef struct {
 | |
|   TPM2_RESPONSE_HEADER       Header;
 | |
|   UINT32                     AuthSessionSize;
 | |
|   TPMI_YES_NO                AllocationSuccess;
 | |
|   UINT32                     MaxPCR;
 | |
|   UINT32                     SizeNeeded;
 | |
|   UINT32                     SizeAvailable;
 | |
|   TPMS_AUTH_RESPONSE         AuthSession;
 | |
| } TPM2_PCR_ALLOCATE_RESPONSE;
 | |
| 
 | |
| #pragma pack()
 | |
| 
 | |
| /**
 | |
|   This command is used to cause an update to the indicated PCR.
 | |
|   The digests parameter contains one or more tagged digest value identified by an algorithm ID.
 | |
|   For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
 | |
| 
 | |
|   @param[in] PcrHandle   Handle of the PCR
 | |
|   @param[in] Digests     List of tagged digest values to be extended
 | |
| 
 | |
|   @retval EFI_SUCCESS      Operation completed successfully.
 | |
|   @retval EFI_DEVICE_ERROR Unexpected device behavior.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Tpm2PcrExtend (
 | |
|   IN      TPMI_DH_PCR               PcrHandle,
 | |
|   IN      TPML_DIGEST_VALUES        *Digests
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   TPM2_PCR_EXTEND_COMMAND           Cmd;
 | |
|   TPM2_PCR_EXTEND_RESPONSE          Res;
 | |
|   UINT32                            CmdSize;
 | |
|   UINT32                            RespSize;
 | |
|   UINT32                            ResultBufSize;
 | |
|   UINT8                             *Buffer;
 | |
|   UINTN                             Index;
 | |
|   UINT32                            SessionInfoSize;
 | |
|   UINT16                            DigestSize;
 | |
| 
 | |
|   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
 | |
|   Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend);
 | |
|   Cmd.PcrHandle          = SwapBytes32(PcrHandle);
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Add in Auth session
 | |
|   //
 | |
|   Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
 | |
|   
 | |
|   // sessionInfoSize
 | |
|   SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
 | |
|   Buffer += SessionInfoSize;
 | |
|   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
 | |
|   
 | |
|   //Digest Count
 | |
|   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count));
 | |
|   Buffer += sizeof(UINT32);
 | |
|   
 | |
|   //Digest
 | |
|   for (Index = 0; Index < Digests->count; Index++) {
 | |
|     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg));
 | |
|     Buffer += sizeof(UINT16);
 | |
|     DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
 | |
|     if (DigestSize == 0) {
 | |
|       DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     CopyMem(
 | |
|       Buffer,
 | |
|       &Digests->digests[Index].digest,
 | |
|       DigestSize
 | |
|       );
 | |
|     Buffer += DigestSize;
 | |
|   }
 | |
| 
 | |
|   CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
 | |
|   Cmd.Header.paramSize = SwapBytes32(CmdSize);
 | |
| 
 | |
|   ResultBufSize = sizeof(Res);
 | |
|   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (ResultBufSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Validate response headers
 | |
|   //
 | |
|   RespSize = SwapBytes32(Res.Header.paramSize);
 | |
|   if (RespSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fail if command failed
 | |
|   //
 | |
|   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Unmarshal the response
 | |
|   //
 | |
| 
 | |
|   // None
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This command is used to cause an update to the indicated PCR.
 | |
|   The data in eventData is hashed using the hash algorithm associated with each bank in which the
 | |
|   indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
 | |
|   references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
 | |
|   TPM2_PCR_Extend().
 | |
|   A TPM shall support an Event.size of zero through 1,024 inclusive.
 | |
| 
 | |
|   @param[in]  PcrHandle   Handle of the PCR
 | |
|   @param[in]  EventData   Event data in sized buffer
 | |
|   @param[out] Digests     List of digest
 | |
| 
 | |
|   @retval EFI_SUCCESS      Operation completed successfully.
 | |
|   @retval EFI_DEVICE_ERROR Unexpected device behavior.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Tpm2PcrEvent (
 | |
|   IN      TPMI_DH_PCR               PcrHandle,
 | |
|   IN      TPM2B_EVENT               *EventData,
 | |
|      OUT  TPML_DIGEST_VALUES        *Digests
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   TPM2_PCR_EVENT_COMMAND            Cmd;
 | |
|   TPM2_PCR_EVENT_RESPONSE           Res;
 | |
|   UINT32                            CmdSize;
 | |
|   UINT32                            RespSize;
 | |
|   UINT32                            ResultBufSize;
 | |
|   UINT8                             *Buffer;
 | |
|   UINTN                             Index;
 | |
|   UINT32                            SessionInfoSize;
 | |
|   UINT16                            DigestSize;
 | |
| 
 | |
|   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
 | |
|   Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Event);
 | |
|   Cmd.PcrHandle          = SwapBytes32(PcrHandle);
 | |
| 
 | |
|   //
 | |
|   // Add in Auth session
 | |
|   //
 | |
|   Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
 | |
| 
 | |
|   // sessionInfoSize
 | |
|   SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
 | |
|   Buffer += SessionInfoSize;
 | |
|   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
 | |
| 
 | |
|   // Event
 | |
|   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(EventData->size));
 | |
|   Buffer += sizeof(UINT16);
 | |
| 
 | |
|   CopyMem (Buffer, EventData->buffer, EventData->size);
 | |
|   Buffer += EventData->size;
 | |
|   
 | |
|   CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
 | |
|   Cmd.Header.paramSize = SwapBytes32(CmdSize);
 | |
| 
 | |
|   ResultBufSize = sizeof(Res);
 | |
|   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (ResultBufSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Validate response headers
 | |
|   //
 | |
|   RespSize = SwapBytes32(Res.Header.paramSize);
 | |
|   if (RespSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fail if command failed
 | |
|   //
 | |
|   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Unmarshal the response
 | |
|   //
 | |
|   Buffer = (UINT8 *)&Res.Digests;
 | |
| 
 | |
|   Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
 | |
|   Buffer += sizeof(UINT32);
 | |
|   for (Index = 0; Index < Digests->count; Index++) {
 | |
|     Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
 | |
|     Buffer += sizeof(UINT16);
 | |
|     DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
 | |
|     if (DigestSize == 0) {
 | |
|       DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     CopyMem(
 | |
|       &Digests->digests[Index].digest,
 | |
|       Buffer,
 | |
|       DigestSize
 | |
|       );
 | |
|     Buffer += DigestSize;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This command returns the values of all PCR specified in pcrSelect.
 | |
| 
 | |
|   @param[in]  PcrSelectionIn     The selection of PCR to read.
 | |
|   @param[out] PcrUpdateCounter   The current value of the PCR update counter.
 | |
|   @param[out] PcrSelectionOut    The PCR in the returned list.
 | |
|   @param[out] PcrValues          The contents of the PCR indicated in pcrSelect.
 | |
|   
 | |
|   @retval EFI_SUCCESS            Operation completed successfully.
 | |
|   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Tpm2PcrRead (
 | |
|   IN      TPML_PCR_SELECTION        *PcrSelectionIn,
 | |
|      OUT  UINT32                    *PcrUpdateCounter,
 | |
|      OUT  TPML_PCR_SELECTION        *PcrSelectionOut,
 | |
|      OUT  TPML_DIGEST               *PcrValues
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   TPM2_PCR_READ_COMMAND             SendBuffer;
 | |
|   TPM2_PCR_READ_RESPONSE            RecvBuffer;
 | |
|   UINT32                            SendBufferSize;
 | |
|   UINT32                            RecvBufferSize;
 | |
|   UINTN                             Index;
 | |
|   TPML_DIGEST                       *PcrValuesOut;
 | |
|   TPM2B_DIGEST                      *Digests;
 | |
| 
 | |
|   //
 | |
|   // Construct command
 | |
|   //
 | |
|   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
 | |
|   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PCR_Read);
 | |
|  
 | |
|   SendBuffer.PcrSelectionIn.count = SwapBytes32(PcrSelectionIn->count);
 | |
|   for (Index = 0; Index < PcrSelectionIn->count; Index++) {
 | |
|     SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16(PcrSelectionIn->pcrSelections[Index].hash);
 | |
|     SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
 | |
|     CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
 | |
|   }
 | |
| 
 | |
|   SendBufferSize = sizeof(SendBuffer.Header) + sizeof(SendBuffer.PcrSelectionIn.count) + sizeof(SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
 | |
|   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
 | |
| 
 | |
|   //
 | |
|   // send Tpm command
 | |
|   //
 | |
|   RecvBufferSize = sizeof (RecvBuffer);
 | |
|   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Return the response
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // PcrUpdateCounter
 | |
|   //
 | |
|   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter);
 | |
| 
 | |
|   //
 | |
|   // PcrSelectionOut
 | |
|   //
 | |
|   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count);
 | |
|   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   for (Index = 0; Index < PcrSelectionOut->count; Index++) {
 | |
|     PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16(RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
 | |
|     PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
 | |
|     CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // PcrValues
 | |
|   //
 | |
|   PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
 | |
|   PcrValues->count = SwapBytes32(PcrValuesOut->count);
 | |
|   Digests = PcrValuesOut->digests;
 | |
|   for (Index = 0; Index < PcrValues->count; Index++) {
 | |
|     PcrValues->digests[Index].size = SwapBytes16(Digests->size);
 | |
|     CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
 | |
|     Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof(Digests->size) + PcrValues->digests[Index].size);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This command is used to set the desired PCR allocation of PCR and algorithms.
 | |
| 
 | |
|   @param[in]  AuthHandle         TPM_RH_PLATFORM+{PP}
 | |
|   @param[in]  AuthSession        Auth Session context
 | |
|   @param[in]  PcrAllocation      The requested allocation
 | |
|   @param[out] AllocationSuccess  YES if the allocation succeeded
 | |
|   @param[out] MaxPCR             maximum number of PCR that may be in a bank
 | |
|   @param[out] SizeNeeded         number of octets required to satisfy the request
 | |
|   @param[out] SizeAvailable      Number of octets available. Computed before the allocation
 | |
|   
 | |
|   @retval EFI_SUCCESS            Operation completed successfully.
 | |
|   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Tpm2PcrAllocate (
 | |
|   IN  TPMI_RH_PLATFORM          AuthHandle,
 | |
|   IN  TPMS_AUTH_COMMAND         *AuthSession,
 | |
|   IN  TPML_PCR_SELECTION        *PcrAllocation,
 | |
|   OUT TPMI_YES_NO               *AllocationSuccess,
 | |
|   OUT UINT32                    *MaxPCR,
 | |
|   OUT UINT32                    *SizeNeeded,
 | |
|   OUT UINT32                    *SizeAvailable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   TPM2_PCR_ALLOCATE_COMMAND   Cmd;
 | |
|   TPM2_PCR_ALLOCATE_RESPONSE  Res;
 | |
|   UINT32                      CmdSize;
 | |
|   UINT32                      RespSize;
 | |
|   UINT8                       *Buffer;
 | |
|   UINT32                      SessionInfoSize;
 | |
|   UINT8                       *ResultBuf;
 | |
|   UINT32                      ResultBufSize;
 | |
|   UINTN                       Index;
 | |
| 
 | |
|   //
 | |
|   // Construct command
 | |
|   //
 | |
|   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
 | |
|   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
 | |
|   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_PCR_Allocate);
 | |
|   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
 | |
| 
 | |
|   //
 | |
|   // Add in Auth session
 | |
|   //
 | |
|   Buffer = (UINT8 *)&Cmd.AuthSession;
 | |
| 
 | |
|   // sessionInfoSize
 | |
|   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
 | |
|   Buffer += SessionInfoSize;
 | |
|   Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize);
 | |
| 
 | |
|   // Count
 | |
|   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count));
 | |
|   Buffer += sizeof(UINT32);
 | |
|   for (Index = 0; Index < PcrAllocation->count; Index++) {
 | |
|     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash));
 | |
|     Buffer += sizeof(UINT16);
 | |
|     *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
 | |
|     Buffer++;
 | |
|     CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
 | |
|     Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
 | |
|   }
 | |
| 
 | |
|   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
 | |
|   Cmd.Header.paramSize = SwapBytes32(CmdSize);
 | |
| 
 | |
|   ResultBuf     = (UINT8 *) &Res;
 | |
|   ResultBufSize = sizeof(Res);
 | |
| 
 | |
|   //
 | |
|   // Call the TPM
 | |
|   //
 | |
|   Status = Tpm2SubmitCommand (
 | |
|              CmdSize, 
 | |
|              (UINT8 *)&Cmd, 
 | |
|              &ResultBufSize,
 | |
|              ResultBuf
 | |
|              );
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (ResultBufSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
 | |
|     Status = EFI_BUFFER_TOO_SMALL;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Validate response headers
 | |
|   //
 | |
|   RespSize = SwapBytes32(Res.Header.paramSize);
 | |
|   if (RespSize > sizeof(Res)) {
 | |
|     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
 | |
|     Status = EFI_BUFFER_TOO_SMALL;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fail if command failed
 | |
|   //
 | |
|   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
 | |
|     DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Return the response
 | |
|   //
 | |
|   *AllocationSuccess = Res.AllocationSuccess;
 | |
|   *MaxPCR = SwapBytes32(Res.MaxPCR);
 | |
|   *SizeNeeded = SwapBytes32(Res.SizeNeeded);
 | |
|   *SizeAvailable = SwapBytes32(Res.SizeAvailable);
 | |
| 
 | |
| Done:
 | |
|   //
 | |
|   // Clear AuthSession Content
 | |
|   //
 | |
|   ZeroMem (&Cmd, sizeof(Cmd));
 | |
|   ZeroMem (&Res, sizeof(Res));
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Alloc PCR data.
 | |
| 
 | |
|   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
 | |
|   @param[in]  SupportedPCRBanks Supported PCR banks
 | |
|   @param[in]  PCRBanks          PCR banks
 | |
|   
 | |
|   @retval EFI_SUCCESS Operation completed successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Tpm2PcrAllocateBanks (
 | |
|   IN TPM2B_AUTH                *PlatformAuth,  OPTIONAL
 | |
|   IN UINT32                    SupportedPCRBanks,
 | |
|   IN UINT32                    PCRBanks
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   TPMS_AUTH_COMMAND         *AuthSession;
 | |
|   TPMS_AUTH_COMMAND         LocalAuthSession;
 | |
|   TPML_PCR_SELECTION        PcrAllocation;
 | |
|   TPMI_YES_NO               AllocationSuccess;
 | |
|   UINT32                    MaxPCR;
 | |
|   UINT32                    SizeNeeded;
 | |
|   UINT32                    SizeAvailable;
 | |
| 
 | |
|   if (PlatformAuth == NULL) {
 | |
|     AuthSession = NULL;
 | |
|   } else {
 | |
|     AuthSession = &LocalAuthSession;
 | |
|     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
 | |
|     LocalAuthSession.sessionHandle = TPM_RS_PW;
 | |
|     LocalAuthSession.hmac.size = PlatformAuth->size;
 | |
|     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fill input
 | |
|   //
 | |
|   ZeroMem (&PcrAllocation, sizeof(PcrAllocation));
 | |
|   if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
 | |
|     if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
 | |
|     } else {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
 | |
|     }
 | |
|     PcrAllocation.count++;
 | |
|   }
 | |
|   if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
 | |
|     if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
 | |
|     } else {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
 | |
|     }
 | |
|     PcrAllocation.count++;
 | |
|   }
 | |
|   if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
 | |
|     if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
 | |
|     } else {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
 | |
|     }
 | |
|     PcrAllocation.count++;
 | |
|   }
 | |
|   if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
 | |
|     if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
 | |
|     } else {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
 | |
|     }
 | |
|     PcrAllocation.count++;
 | |
|   }
 | |
|   if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
 | |
|     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
 | |
|     if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
 | |
|     } else {
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
 | |
|       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
 | |
|     }
 | |
|     PcrAllocation.count++;
 | |
|   }
 | |
|   Status = Tpm2PcrAllocate (
 | |
|              TPM_RH_PLATFORM,
 | |
|              AuthSession,
 | |
|              &PcrAllocation,
 | |
|              &AllocationSuccess,
 | |
|              &MaxPCR,
 | |
|              &SizeNeeded,
 | |
|              &SizeAvailable
 | |
|              );
 | |
|   DEBUG ((EFI_D_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
 | |
|   DEBUG ((EFI_D_INFO, "MaxPCR            - %08x\n", MaxPCR));
 | |
|   DEBUG ((EFI_D_INFO, "SizeNeeded        - %08x\n", SizeNeeded));
 | |
|   DEBUG ((EFI_D_INFO, "SizeAvailable     - %08x\n", SizeAvailable));
 | |
| 
 | |
| Done:
 | |
|   ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
 | |
|   return Status;
 | |
| } |