1 /** @file
2   Implement TPM1.2 NV storage related command.
3 
4 Copyright (c) 2015, 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 <Uefi.h>
16 #include <IndustryStandard/Tpm12.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/Tpm12DeviceLib.h>
20 #include <Library/Tpm12CommandLib.h>
21 #include <Library/DebugLib.h>
22 
23 //
24 // Max TPM command/reponse length
25 //
26 #define TPMCMDBUFLENGTH             1024
27 
28 #pragma pack(1)
29 
30 typedef struct {
31   TPM_RQU_COMMAND_HDR   Hdr;
32   TPM12_NV_DATA_PUBLIC  PubInfo;
33   TPM_ENCAUTH           EncAuth;
34 } TPM_CMD_NV_DEFINE_SPACE;
35 
36 typedef struct {
37   TPM_RSP_COMMAND_HDR   Hdr;
38 } TPM_RSP_NV_DEFINE_SPACE;
39 
40 typedef struct {
41   TPM_RQU_COMMAND_HDR   Hdr;
42   TPM_NV_INDEX          NvIndex;
43   UINT32                Offset;
44   UINT32                DataSize;
45 } TPM_CMD_NV_READ_VALUE;
46 
47 typedef struct {
48   TPM_RSP_COMMAND_HDR   Hdr;
49   UINT32                DataSize;
50   UINT8                 Data[TPMCMDBUFLENGTH];
51 } TPM_RSP_NV_READ_VALUE;
52 
53 typedef struct {
54   TPM_RQU_COMMAND_HDR   Hdr;
55   TPM_NV_INDEX          NvIndex;
56   UINT32                Offset;
57   UINT32                DataSize;
58   UINT8                 Data[TPMCMDBUFLENGTH];
59 } TPM_CMD_NV_WRITE_VALUE;
60 
61 typedef struct {
62   TPM_RSP_COMMAND_HDR   Hdr;
63 } TPM_RSP_NV_WRITE_VALUE;
64 
65 #pragma pack()
66 
67 /**
68   Send NV DefineSpace command to TPM1.2.
69 
70   @param PubInfo           The public parameters of the NV area.
71   @param EncAuth           The encrypted AuthData, only valid if the attributes require subsequent authorization.
72 
73   @retval EFI_SUCCESS      Operation completed successfully.
74   @retval EFI_DEVICE_ERROR Unexpected device behavior.
75 **/
76 EFI_STATUS
77 EFIAPI
Tpm12NvDefineSpace(IN TPM12_NV_DATA_PUBLIC * PubInfo,IN TPM_ENCAUTH * EncAuth)78 Tpm12NvDefineSpace (
79   IN TPM12_NV_DATA_PUBLIC  *PubInfo,
80   IN TPM_ENCAUTH           *EncAuth
81   )
82 {
83   EFI_STATUS                        Status;
84   UINT32                            TpmRecvSize;
85   UINT32                            TpmSendSize;
86   TPM_CMD_NV_DEFINE_SPACE           SendBuffer;
87   TPM_RSP_NV_DEFINE_SPACE           RecvBuffer;
88   UINT32                            ReturnCode;
89 
90   //
91   // send Tpm command TPM_ORD_NV_DefineSpace
92   //
93   TpmRecvSize                = sizeof (TPM_RSP_NV_DEFINE_SPACE);
94   TpmSendSize                = sizeof (TPM_CMD_NV_DEFINE_SPACE);
95   SendBuffer.Hdr.tag         = SwapBytes16 (TPM_TAG_RQU_COMMAND);
96   SendBuffer.Hdr.paramSize   = SwapBytes32 (sizeof(TPM_CMD_NV_DEFINE_SPACE));
97   SendBuffer.Hdr.ordinal     = SwapBytes32 (TPM_ORD_NV_DefineSpace);
98   SendBuffer.PubInfo.tag     = SwapBytes16 (PubInfo->tag);
99   SendBuffer.PubInfo.nvIndex = SwapBytes32 (PubInfo->nvIndex);
100   SendBuffer.PubInfo.pcrInfoRead.pcrSelection.sizeOfSelect  = SwapBytes16 (PubInfo->pcrInfoRead.pcrSelection.sizeOfSelect);
101   SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[0]  = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[0];
102   SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[1]  = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[1];
103   SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[2]  = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[2];
104   SendBuffer.PubInfo.pcrInfoRead.localityAtRelease          = PubInfo->pcrInfoRead.localityAtRelease;
105   CopyMem (&SendBuffer.PubInfo.pcrInfoRead.digestAtRelease, &PubInfo->pcrInfoRead.digestAtRelease, sizeof(PubInfo->pcrInfoRead.digestAtRelease));
106   SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.sizeOfSelect = SwapBytes16 (PubInfo->pcrInfoWrite.pcrSelection.sizeOfSelect);
107   SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[0] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[0];
108   SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[1] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[1];
109   SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[2] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[2];
110   SendBuffer.PubInfo.pcrInfoWrite.localityAtRelease         = PubInfo->pcrInfoWrite.localityAtRelease;
111   CopyMem (&SendBuffer.PubInfo.pcrInfoWrite.digestAtRelease, &PubInfo->pcrInfoWrite.digestAtRelease, sizeof(PubInfo->pcrInfoWrite.digestAtRelease));
112   SendBuffer.PubInfo.permission.tag        = SwapBytes16 (PubInfo->permission.tag);
113   SendBuffer.PubInfo.permission.attributes = SwapBytes32 (PubInfo->permission.attributes);
114   SendBuffer.PubInfo.bReadSTClear          = PubInfo->bReadSTClear;
115   SendBuffer.PubInfo.bWriteSTClear         = PubInfo->bWriteSTClear;
116   SendBuffer.PubInfo.bWriteDefine          = PubInfo->bWriteDefine;
117   SendBuffer.PubInfo.dataSize              = SwapBytes32 (PubInfo->dataSize);
118   CopyMem (&SendBuffer.EncAuth, EncAuth, sizeof(*EncAuth));
119 
120   Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer);
121   if (EFI_ERROR (Status)) {
122     return Status;
123   }
124   ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode);
125   DEBUG ((DEBUG_INFO, "Tpm12NvDefineSpace - ReturnCode = %x\n", ReturnCode));
126   switch (ReturnCode) {
127   case TPM_SUCCESS:
128     break;
129   default:
130     return EFI_DEVICE_ERROR;
131   }
132 
133   return EFI_SUCCESS;
134 }
135 
136 /**
137   Send NV ReadValue command to TPM1.2.
138 
139   @param NvIndex           The index of the area to set.
140   @param Offset            The offset into the area.
141   @param DataSize          The size of the data area.
142   @param Data              The data to set the area to.
143 
144   @retval EFI_SUCCESS      Operation completed successfully.
145   @retval EFI_DEVICE_ERROR Unexpected device behavior.
146 **/
147 EFI_STATUS
148 EFIAPI
Tpm12NvReadValue(IN TPM_NV_INDEX NvIndex,IN UINT32 Offset,IN OUT UINT32 * DataSize,OUT UINT8 * Data)149 Tpm12NvReadValue (
150   IN TPM_NV_INDEX   NvIndex,
151   IN UINT32         Offset,
152   IN OUT UINT32     *DataSize,
153   OUT UINT8         *Data
154   )
155 {
156   EFI_STATUS                        Status;
157   UINT32                            TpmRecvSize;
158   UINT32                            TpmSendSize;
159   TPM_CMD_NV_READ_VALUE             SendBuffer;
160   TPM_RSP_NV_READ_VALUE             RecvBuffer;
161   UINT32                            ReturnCode;
162 
163   //
164   // send Tpm command TPM_ORD_NV_ReadValue
165   //
166   TpmRecvSize               = sizeof (TPM_RSP_NV_READ_VALUE);
167   TpmSendSize               = sizeof (TPM_CMD_NV_READ_VALUE);
168   SendBuffer.Hdr.tag        = SwapBytes16 (TPM_TAG_RQU_COMMAND);
169   SendBuffer.Hdr.paramSize  = SwapBytes32 (sizeof(TPM_CMD_NV_READ_VALUE));
170   SendBuffer.Hdr.ordinal    = SwapBytes32 (TPM_ORD_NV_ReadValue);
171   SendBuffer.NvIndex        = SwapBytes32 (NvIndex);
172   SendBuffer.Offset         = SwapBytes32 (Offset);
173   SendBuffer.DataSize       = SwapBytes32 (*DataSize);
174 
175   Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer);
176   if (EFI_ERROR (Status)) {
177     return Status;
178   }
179   ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode);
180   DEBUG ((DEBUG_INFO, "Tpm12NvReadValue - ReturnCode = %x\n", ReturnCode));
181   switch (ReturnCode) {
182   case TPM_SUCCESS:
183     break;
184   default:
185     return EFI_DEVICE_ERROR;
186   }
187 
188   //
189   // Return the response
190   //
191   *DataSize = SwapBytes32(RecvBuffer.DataSize);
192   CopyMem (Data, &RecvBuffer.Data, *DataSize);
193 
194   return EFI_SUCCESS;
195 }
196 
197 /**
198   Send NV WriteValue command to TPM1.2.
199 
200   @param NvIndex           The index of the area to set.
201   @param Offset            The offset into the NV Area.
202   @param DataSize          The size of the data parameter.
203   @param Data              The data to set the area to.
204 
205   @retval EFI_SUCCESS      Operation completed successfully.
206   @retval EFI_DEVICE_ERROR Unexpected device behavior.
207 **/
208 EFI_STATUS
209 EFIAPI
Tpm12NvWriteValue(IN TPM_NV_INDEX NvIndex,IN UINT32 Offset,IN UINT32 DataSize,IN UINT8 * Data)210 Tpm12NvWriteValue (
211   IN TPM_NV_INDEX   NvIndex,
212   IN UINT32         Offset,
213   IN UINT32         DataSize,
214   IN UINT8          *Data
215   )
216 {
217   EFI_STATUS                        Status;
218   UINT32                            TpmRecvSize;
219   UINT32                            TpmSendSize;
220   TPM_CMD_NV_WRITE_VALUE            SendBuffer;
221   TPM_RSP_NV_WRITE_VALUE            RecvBuffer;
222   UINT32                            ReturnCode;
223 
224   if (DataSize > sizeof(SendBuffer.Data)) {
225     return EFI_UNSUPPORTED;
226   }
227 
228   //
229   // send Tpm command TPM_ORD_NV_WriteValue
230   //
231   TpmRecvSize               = sizeof (TPM_RSP_NV_WRITE_VALUE);
232   TpmSendSize               = sizeof (TPM_CMD_NV_WRITE_VALUE) - sizeof(SendBuffer.Data) + DataSize;
233   SendBuffer.Hdr.tag        = SwapBytes16 (TPM_TAG_RQU_COMMAND);
234   SendBuffer.Hdr.paramSize  = SwapBytes32 (sizeof(TPM_CMD_NV_WRITE_VALUE) - sizeof(SendBuffer.Data) + DataSize);
235   SendBuffer.Hdr.ordinal    = SwapBytes32 (TPM_ORD_NV_WriteValue);
236   SendBuffer.NvIndex        = SwapBytes32 (NvIndex);
237   SendBuffer.Offset         = SwapBytes32 (Offset);
238   SendBuffer.DataSize       = SwapBytes32 (DataSize);
239   CopyMem (SendBuffer.Data, Data, DataSize);
240 
241   Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer);
242   if (EFI_ERROR (Status)) {
243     return Status;
244   }
245   ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode);
246   DEBUG ((DEBUG_INFO, "Tpm12NvWritedValue - ReturnCode = %x\n", ReturnCode));
247   switch (ReturnCode) {
248   case TPM_SUCCESS:
249     break;
250   default:
251     return EFI_DEVICE_ERROR;
252   }
253 
254   return EFI_SUCCESS;
255 }
256