Home | History | Annotate | Download | only in Tpm2CommandLib
      1 /** @file
      2   Implement TPM2 Integrity related command.
      3 
      4 Copyright (c) 2013 - 2016, 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_DH_PCR               PcrHandle;
     27   UINT32                    AuthorizationSize;
     28   TPMS_AUTH_COMMAND         AuthSessionPcr;
     29   TPML_DIGEST_VALUES        DigestValues;
     30 } TPM2_PCR_EXTEND_COMMAND;
     31 
     32 typedef struct {
     33   TPM2_RESPONSE_HEADER       Header;
     34   UINT32                     ParameterSize;
     35   TPMS_AUTH_RESPONSE         AuthSessionPcr;
     36 } TPM2_PCR_EXTEND_RESPONSE;
     37 
     38 typedef struct {
     39   TPM2_COMMAND_HEADER       Header;
     40   TPMI_DH_PCR               PcrHandle;
     41   UINT32                    AuthorizationSize;
     42   TPMS_AUTH_COMMAND         AuthSessionPcr;
     43   TPM2B_EVENT               EventData;
     44 } TPM2_PCR_EVENT_COMMAND;
     45 
     46 typedef struct {
     47   TPM2_RESPONSE_HEADER       Header;
     48   UINT32                     ParameterSize;
     49   TPML_DIGEST_VALUES         Digests;
     50   TPMS_AUTH_RESPONSE         AuthSessionPcr;
     51 } TPM2_PCR_EVENT_RESPONSE;
     52 
     53 typedef struct {
     54   TPM2_COMMAND_HEADER       Header;
     55   TPML_PCR_SELECTION        PcrSelectionIn;
     56 } TPM2_PCR_READ_COMMAND;
     57 
     58 typedef struct {
     59   TPM2_RESPONSE_HEADER      Header;
     60   UINT32                    PcrUpdateCounter;
     61   TPML_PCR_SELECTION        PcrSelectionOut;
     62   TPML_DIGEST               PcrValues;
     63 } TPM2_PCR_READ_RESPONSE;
     64 
     65 typedef struct {
     66   TPM2_COMMAND_HEADER       Header;
     67   TPMI_RH_PLATFORM          AuthHandle;
     68   UINT32                    AuthSessionSize;
     69   TPMS_AUTH_COMMAND         AuthSession;
     70   TPML_PCR_SELECTION        PcrAllocation;
     71 } TPM2_PCR_ALLOCATE_COMMAND;
     72 
     73 typedef struct {
     74   TPM2_RESPONSE_HEADER       Header;
     75   UINT32                     AuthSessionSize;
     76   TPMI_YES_NO                AllocationSuccess;
     77   UINT32                     MaxPCR;
     78   UINT32                     SizeNeeded;
     79   UINT32                     SizeAvailable;
     80   TPMS_AUTH_RESPONSE         AuthSession;
     81 } TPM2_PCR_ALLOCATE_RESPONSE;
     82 
     83 #pragma pack()
     84 
     85 /**
     86   This command is used to cause an update to the indicated PCR.
     87   The digests parameter contains one or more tagged digest value identified by an algorithm ID.
     88   For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
     89 
     90   @param[in] PcrHandle   Handle of the PCR
     91   @param[in] Digests     List of tagged digest values to be extended
     92 
     93   @retval EFI_SUCCESS      Operation completed successfully.
     94   @retval EFI_DEVICE_ERROR Unexpected device behavior.
     95 **/
     96 EFI_STATUS
     97 EFIAPI
     98 Tpm2PcrExtend (
     99   IN      TPMI_DH_PCR               PcrHandle,
    100   IN      TPML_DIGEST_VALUES        *Digests
    101   )
    102 {
    103   EFI_STATUS                        Status;
    104   TPM2_PCR_EXTEND_COMMAND           Cmd;
    105   TPM2_PCR_EXTEND_RESPONSE          Res;
    106   UINT32                            CmdSize;
    107   UINT32                            RespSize;
    108   UINT32                            ResultBufSize;
    109   UINT8                             *Buffer;
    110   UINTN                             Index;
    111   UINT32                            SessionInfoSize;
    112   UINT16                            DigestSize;
    113 
    114   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
    115   Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend);
    116   Cmd.PcrHandle          = SwapBytes32(PcrHandle);
    117 
    118 
    119   //
    120   // Add in Auth session
    121   //
    122   Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
    123 
    124   // sessionInfoSize
    125   SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
    126   Buffer += SessionInfoSize;
    127   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
    128 
    129   //Digest Count
    130   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count));
    131   Buffer += sizeof(UINT32);
    132 
    133   //Digest
    134   for (Index = 0; Index < Digests->count; Index++) {
    135     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg));
    136     Buffer += sizeof(UINT16);
    137     DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
    138     if (DigestSize == 0) {
    139       DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
    140       return EFI_DEVICE_ERROR;
    141     }
    142     CopyMem(
    143       Buffer,
    144       &Digests->digests[Index].digest,
    145       DigestSize
    146       );
    147     Buffer += DigestSize;
    148   }
    149 
    150   CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
    151   Cmd.Header.paramSize = SwapBytes32(CmdSize);
    152 
    153   ResultBufSize = sizeof(Res);
    154   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
    155   if (EFI_ERROR(Status)) {
    156     return Status;
    157   }
    158 
    159   if (ResultBufSize > sizeof(Res)) {
    160     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
    161     return EFI_BUFFER_TOO_SMALL;
    162   }
    163 
    164   //
    165   // Validate response headers
    166   //
    167   RespSize = SwapBytes32(Res.Header.paramSize);
    168   if (RespSize > sizeof(Res)) {
    169     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
    170     return EFI_BUFFER_TOO_SMALL;
    171   }
    172 
    173   //
    174   // Fail if command failed
    175   //
    176   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
    177     DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
    178     return EFI_DEVICE_ERROR;
    179   }
    180 
    181   //
    182   // Unmarshal the response
    183   //
    184 
    185   // None
    186 
    187   return EFI_SUCCESS;
    188 }
    189 
    190 /**
    191   This command is used to cause an update to the indicated PCR.
    192   The data in eventData is hashed using the hash algorithm associated with each bank in which the
    193   indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
    194   references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
    195   TPM2_PCR_Extend().
    196   A TPM shall support an Event.size of zero through 1,024 inclusive.
    197 
    198   @param[in]  PcrHandle   Handle of the PCR
    199   @param[in]  EventData   Event data in sized buffer
    200   @param[out] Digests     List of digest
    201 
    202   @retval EFI_SUCCESS      Operation completed successfully.
    203   @retval EFI_DEVICE_ERROR Unexpected device behavior.
    204 **/
    205 EFI_STATUS
    206 EFIAPI
    207 Tpm2PcrEvent (
    208   IN      TPMI_DH_PCR               PcrHandle,
    209   IN      TPM2B_EVENT               *EventData,
    210      OUT  TPML_DIGEST_VALUES        *Digests
    211   )
    212 {
    213   EFI_STATUS                        Status;
    214   TPM2_PCR_EVENT_COMMAND            Cmd;
    215   TPM2_PCR_EVENT_RESPONSE           Res;
    216   UINT32                            CmdSize;
    217   UINT32                            RespSize;
    218   UINT32                            ResultBufSize;
    219   UINT8                             *Buffer;
    220   UINTN                             Index;
    221   UINT32                            SessionInfoSize;
    222   UINT16                            DigestSize;
    223 
    224   Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);
    225   Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Event);
    226   Cmd.PcrHandle          = SwapBytes32(PcrHandle);
    227 
    228   //
    229   // Add in Auth session
    230   //
    231   Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
    232 
    233   // sessionInfoSize
    234   SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
    235   Buffer += SessionInfoSize;
    236   Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
    237 
    238   // Event
    239   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(EventData->size));
    240   Buffer += sizeof(UINT16);
    241 
    242   CopyMem (Buffer, EventData->buffer, EventData->size);
    243   Buffer += EventData->size;
    244 
    245   CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
    246   Cmd.Header.paramSize = SwapBytes32(CmdSize);
    247 
    248   ResultBufSize = sizeof(Res);
    249   Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
    250   if (EFI_ERROR(Status)) {
    251     return Status;
    252   }
    253 
    254   if (ResultBufSize > sizeof(Res)) {
    255     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
    256     return EFI_BUFFER_TOO_SMALL;
    257   }
    258 
    259   //
    260   // Validate response headers
    261   //
    262   RespSize = SwapBytes32(Res.Header.paramSize);
    263   if (RespSize > sizeof(Res)) {
    264     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
    265     return EFI_BUFFER_TOO_SMALL;
    266   }
    267 
    268   //
    269   // Fail if command failed
    270   //
    271   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
    272     DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
    273     return EFI_DEVICE_ERROR;
    274   }
    275 
    276   //
    277   // Unmarshal the response
    278   //
    279   Buffer = (UINT8 *)&Res.Digests;
    280 
    281   Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
    282   Buffer += sizeof(UINT32);
    283   for (Index = 0; Index < Digests->count; Index++) {
    284     Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
    285     Buffer += sizeof(UINT16);
    286     DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
    287     if (DigestSize == 0) {
    288       DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
    289       return EFI_DEVICE_ERROR;
    290     }
    291     CopyMem(
    292       &Digests->digests[Index].digest,
    293       Buffer,
    294       DigestSize
    295       );
    296     Buffer += DigestSize;
    297   }
    298 
    299   return EFI_SUCCESS;
    300 }
    301 
    302 /**
    303   This command returns the values of all PCR specified in pcrSelect.
    304 
    305   @param[in]  PcrSelectionIn     The selection of PCR to read.
    306   @param[out] PcrUpdateCounter   The current value of the PCR update counter.
    307   @param[out] PcrSelectionOut    The PCR in the returned list.
    308   @param[out] PcrValues          The contents of the PCR indicated in pcrSelect.
    309 
    310   @retval EFI_SUCCESS            Operation completed successfully.
    311   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    312 **/
    313 EFI_STATUS
    314 EFIAPI
    315 Tpm2PcrRead (
    316   IN      TPML_PCR_SELECTION        *PcrSelectionIn,
    317      OUT  UINT32                    *PcrUpdateCounter,
    318      OUT  TPML_PCR_SELECTION        *PcrSelectionOut,
    319      OUT  TPML_DIGEST               *PcrValues
    320   )
    321 {
    322   EFI_STATUS                        Status;
    323   TPM2_PCR_READ_COMMAND             SendBuffer;
    324   TPM2_PCR_READ_RESPONSE            RecvBuffer;
    325   UINT32                            SendBufferSize;
    326   UINT32                            RecvBufferSize;
    327   UINTN                             Index;
    328   TPML_DIGEST                       *PcrValuesOut;
    329   TPM2B_DIGEST                      *Digests;
    330 
    331   //
    332   // Construct command
    333   //
    334   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
    335   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PCR_Read);
    336 
    337   SendBuffer.PcrSelectionIn.count = SwapBytes32(PcrSelectionIn->count);
    338   for (Index = 0; Index < PcrSelectionIn->count; Index++) {
    339     SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16(PcrSelectionIn->pcrSelections[Index].hash);
    340     SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
    341     CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
    342   }
    343 
    344   SendBufferSize = sizeof(SendBuffer.Header) + sizeof(SendBuffer.PcrSelectionIn.count) + sizeof(SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
    345   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    346 
    347   //
    348   // send Tpm command
    349   //
    350   RecvBufferSize = sizeof (RecvBuffer);
    351   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    352   if (EFI_ERROR (Status)) {
    353     return Status;
    354   }
    355 
    356   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    357     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
    358     return EFI_DEVICE_ERROR;
    359   }
    360   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    361     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    362     return EFI_NOT_FOUND;
    363   }
    364 
    365   //
    366   // Return the response
    367   //
    368 
    369   //
    370   // PcrUpdateCounter
    371   //
    372   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) {
    373     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
    374     return EFI_DEVICE_ERROR;
    375   }
    376   *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter);
    377 
    378   //
    379   // PcrSelectionOut
    380   //
    381   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) {
    382     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
    383     return EFI_DEVICE_ERROR;
    384   }
    385   PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count);
    386   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
    387     DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
    388     return EFI_DEVICE_ERROR;
    389   }
    390   for (Index = 0; Index < PcrSelectionOut->count; Index++) {
    391     PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16(RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
    392     PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
    393     CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
    394   }
    395 
    396   //
    397   // PcrValues
    398   //
    399   PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
    400   PcrValues->count = SwapBytes32(PcrValuesOut->count);
    401   Digests = PcrValuesOut->digests;
    402   for (Index = 0; Index < PcrValues->count; Index++) {
    403     PcrValues->digests[Index].size = SwapBytes16(Digests->size);
    404     CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
    405     Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof(Digests->size) + PcrValues->digests[Index].size);
    406   }
    407 
    408   return EFI_SUCCESS;
    409 }
    410 
    411 /**
    412   This command is used to set the desired PCR allocation of PCR and algorithms.
    413 
    414   @param[in]  AuthHandle         TPM_RH_PLATFORM+{PP}
    415   @param[in]  AuthSession        Auth Session context
    416   @param[in]  PcrAllocation      The requested allocation
    417   @param[out] AllocationSuccess  YES if the allocation succeeded
    418   @param[out] MaxPCR             maximum number of PCR that may be in a bank
    419   @param[out] SizeNeeded         number of octets required to satisfy the request
    420   @param[out] SizeAvailable      Number of octets available. Computed before the allocation
    421 
    422   @retval EFI_SUCCESS            Operation completed successfully.
    423   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    424 **/
    425 EFI_STATUS
    426 EFIAPI
    427 Tpm2PcrAllocate (
    428   IN  TPMI_RH_PLATFORM          AuthHandle,
    429   IN  TPMS_AUTH_COMMAND         *AuthSession,
    430   IN  TPML_PCR_SELECTION        *PcrAllocation,
    431   OUT TPMI_YES_NO               *AllocationSuccess,
    432   OUT UINT32                    *MaxPCR,
    433   OUT UINT32                    *SizeNeeded,
    434   OUT UINT32                    *SizeAvailable
    435   )
    436 {
    437   EFI_STATUS                  Status;
    438   TPM2_PCR_ALLOCATE_COMMAND   Cmd;
    439   TPM2_PCR_ALLOCATE_RESPONSE  Res;
    440   UINT32                      CmdSize;
    441   UINT32                      RespSize;
    442   UINT8                       *Buffer;
    443   UINT32                      SessionInfoSize;
    444   UINT8                       *ResultBuf;
    445   UINT32                      ResultBufSize;
    446   UINTN                       Index;
    447 
    448   //
    449   // Construct command
    450   //
    451   Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);
    452   Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));
    453   Cmd.Header.commandCode  = SwapBytes32(TPM_CC_PCR_Allocate);
    454   Cmd.AuthHandle          = SwapBytes32(AuthHandle);
    455 
    456   //
    457   // Add in Auth session
    458   //
    459   Buffer = (UINT8 *)&Cmd.AuthSession;
    460 
    461   // sessionInfoSize
    462   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
    463   Buffer += SessionInfoSize;
    464   Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize);
    465 
    466   // Count
    467   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count));
    468   Buffer += sizeof(UINT32);
    469   for (Index = 0; Index < PcrAllocation->count; Index++) {
    470     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash));
    471     Buffer += sizeof(UINT16);
    472     *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
    473     Buffer++;
    474     CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
    475     Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
    476   }
    477 
    478   CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
    479   Cmd.Header.paramSize = SwapBytes32(CmdSize);
    480 
    481   ResultBuf     = (UINT8 *) &Res;
    482   ResultBufSize = sizeof(Res);
    483 
    484   //
    485   // Call the TPM
    486   //
    487   Status = Tpm2SubmitCommand (
    488              CmdSize,
    489              (UINT8 *)&Cmd,
    490              &ResultBufSize,
    491              ResultBuf
    492              );
    493   if (EFI_ERROR(Status)) {
    494     goto Done;
    495   }
    496 
    497   if (ResultBufSize > sizeof(Res)) {
    498     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
    499     Status = EFI_BUFFER_TOO_SMALL;
    500     goto Done;
    501   }
    502 
    503   //
    504   // Validate response headers
    505   //
    506   RespSize = SwapBytes32(Res.Header.paramSize);
    507   if (RespSize > sizeof(Res)) {
    508     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
    509     Status = EFI_BUFFER_TOO_SMALL;
    510     goto Done;
    511   }
    512 
    513   //
    514   // Fail if command failed
    515   //
    516   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
    517     DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
    518     Status = EFI_DEVICE_ERROR;
    519     goto Done;
    520   }
    521 
    522   //
    523   // Return the response
    524   //
    525   *AllocationSuccess = Res.AllocationSuccess;
    526   *MaxPCR = SwapBytes32(Res.MaxPCR);
    527   *SizeNeeded = SwapBytes32(Res.SizeNeeded);
    528   *SizeAvailable = SwapBytes32(Res.SizeAvailable);
    529 
    530 Done:
    531   //
    532   // Clear AuthSession Content
    533   //
    534   ZeroMem (&Cmd, sizeof(Cmd));
    535   ZeroMem (&Res, sizeof(Res));
    536   return Status;
    537 }
    538 
    539 /**
    540   Alloc PCR data.
    541 
    542   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
    543   @param[in]  SupportedPCRBanks Supported PCR banks
    544   @param[in]  PCRBanks          PCR banks
    545 
    546   @retval EFI_SUCCESS Operation completed successfully.
    547 **/
    548 EFI_STATUS
    549 EFIAPI
    550 Tpm2PcrAllocateBanks (
    551   IN TPM2B_AUTH                *PlatformAuth,  OPTIONAL
    552   IN UINT32                    SupportedPCRBanks,
    553   IN UINT32                    PCRBanks
    554   )
    555 {
    556   EFI_STATUS                Status;
    557   TPMS_AUTH_COMMAND         *AuthSession;
    558   TPMS_AUTH_COMMAND         LocalAuthSession;
    559   TPML_PCR_SELECTION        PcrAllocation;
    560   TPMI_YES_NO               AllocationSuccess;
    561   UINT32                    MaxPCR;
    562   UINT32                    SizeNeeded;
    563   UINT32                    SizeAvailable;
    564 
    565   if (PlatformAuth == NULL) {
    566     AuthSession = NULL;
    567   } else {
    568     AuthSession = &LocalAuthSession;
    569     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
    570     LocalAuthSession.sessionHandle = TPM_RS_PW;
    571     LocalAuthSession.hmac.size = PlatformAuth->size;
    572     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
    573   }
    574 
    575   //
    576   // Fill input
    577   //
    578   ZeroMem (&PcrAllocation, sizeof(PcrAllocation));
    579   if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
    580     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
    581     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    582     if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
    583       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    584       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    585       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    586     } else {
    587       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    588       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    589       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    590     }
    591     PcrAllocation.count++;
    592   }
    593   if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
    594     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
    595     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    596     if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
    597       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    598       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    599       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    600     } else {
    601       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    602       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    603       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    604     }
    605     PcrAllocation.count++;
    606   }
    607   if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
    608     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
    609     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    610     if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
    611       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    612       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    613       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    614     } else {
    615       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    616       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    617       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    618     }
    619     PcrAllocation.count++;
    620   }
    621   if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
    622     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
    623     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    624     if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
    625       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    626       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    627       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    628     } else {
    629       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    630       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    631       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    632     }
    633     PcrAllocation.count++;
    634   }
    635   if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
    636     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
    637     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    638     if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
    639       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    640       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    641       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    642     } else {
    643       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    644       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    645       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    646     }
    647     PcrAllocation.count++;
    648   }
    649   Status = Tpm2PcrAllocate (
    650              TPM_RH_PLATFORM,
    651              AuthSession,
    652              &PcrAllocation,
    653              &AllocationSuccess,
    654              &MaxPCR,
    655              &SizeNeeded,
    656              &SizeAvailable
    657              );
    658   DEBUG ((EFI_D_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
    659   if (EFI_ERROR (Status)) {
    660     goto Done;
    661   }
    662 
    663   DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
    664   DEBUG ((EFI_D_INFO, "MaxPCR            - %08x\n", MaxPCR));
    665   DEBUG ((EFI_D_INFO, "SizeNeeded        - %08x\n", SizeNeeded));
    666   DEBUG ((EFI_D_INFO, "SizeAvailable     - %08x\n", SizeAvailable));
    667 
    668 Done:
    669   ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
    670   return Status;
    671 }