1 /** @file
2   Implement TPM2 Integrity 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_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
Tpm2PcrExtend(IN TPMI_DH_PCR PcrHandle,IN TPML_DIGEST_VALUES * Digests)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
Tpm2PcrEvent(IN TPMI_DH_PCR PcrHandle,IN TPM2B_EVENT * EventData,OUT TPML_DIGEST_VALUES * Digests)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
Tpm2PcrRead(IN TPML_PCR_SELECTION * PcrSelectionIn,OUT UINT32 * PcrUpdateCounter,OUT TPML_PCR_SELECTION * PcrSelectionOut,OUT TPML_DIGEST * PcrValues)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
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)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 
494   if (ResultBufSize > sizeof(Res)) {
495     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
496     return EFI_BUFFER_TOO_SMALL;
497   }
498 
499   //
500   // Validate response headers
501   //
502   RespSize = SwapBytes32(Res.Header.paramSize);
503   if (RespSize > sizeof(Res)) {
504     DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
505     return EFI_BUFFER_TOO_SMALL;
506   }
507 
508   //
509   // Fail if command failed
510   //
511   if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
512     DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
513     return EFI_DEVICE_ERROR;
514   }
515 
516   //
517   // Return the response
518   //
519   *AllocationSuccess = Res.AllocationSuccess;
520   *MaxPCR = SwapBytes32(Res.MaxPCR);
521   *SizeNeeded = SwapBytes32(Res.SizeNeeded);
522   *SizeAvailable = SwapBytes32(Res.SizeAvailable);
523 
524   return EFI_SUCCESS;
525 }
526