]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
Add TPM2 support defined in trusted computing group.
[mirror_edk2.git] / SecurityPkg / Library / HashLibTpm2 / HashLibTpm2.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Ihis library uses TPM2 device to calculation hash.\r
3\r
1abfa4ce 4Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved. <BR>\r
c1d93242
JY
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/Tpm2CommandLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/HashLib.h>\r
22#include <Library/PcdLib.h>\r
c1d93242
JY
23\r
24typedef struct {\r
25 TPM_ALG_ID AlgoId;\r
26 UINT32 Mask;\r
27} TPM2_HASH_MASK;\r
28\r
29TPM2_HASH_MASK mTpm2HashMask[] = {\r
1abfa4ce
JY
30 {TPM_ALG_SHA1, HASH_ALG_SHA1},\r
31 {TPM_ALG_SHA256, HASH_ALG_SHA256},\r
32 {TPM_ALG_SHA384, HASH_ALG_SHA384},\r
33 {TPM_ALG_SHA512, HASH_ALG_SHA512},\r
c1d93242
JY
34};\r
35\r
36/**\r
37 The function get algorith from hash mask info.\r
38\r
39 @return Hash algorithm\r
40**/\r
41TPM_ALG_ID\r
42Tpm2GetAlgoFromHashMask (\r
43 VOID\r
44 )\r
45{\r
46 UINT32 HashMask;\r
47 UINTN Index;\r
48\r
49 HashMask = PcdGet32 (PcdTpm2HashMask);\r
50 for (Index = 0; Index < sizeof(mTpm2HashMask)/sizeof(mTpm2HashMask[0]); Index++) {\r
51 if (mTpm2HashMask[Index].Mask == HashMask) {\r
52 return mTpm2HashMask[Index].AlgoId;\r
53 }\r
54 }\r
55\r
56 return TPM_ALG_NULL;\r
57}\r
58\r
59/**\r
60 Start hash sequence.\r
61\r
62 @param HashHandle Hash handle.\r
63\r
64 @retval EFI_SUCCESS Hash sequence start and HandleHandle returned.\r
65 @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
66**/\r
67EFI_STATUS\r
68EFIAPI\r
69HashStart (\r
70 OUT HASH_HANDLE *HashHandle\r
71 )\r
72{\r
73 TPMI_DH_OBJECT SequenceHandle;\r
74 EFI_STATUS Status;\r
75 TPM_ALG_ID AlgoId;\r
76\r
77 AlgoId = Tpm2GetAlgoFromHashMask ();\r
78\r
79 Status = Tpm2HashSequenceStart (AlgoId, &SequenceHandle);\r
80 if (!EFI_ERROR (Status)) {\r
81 *HashHandle = (HASH_HANDLE)SequenceHandle;\r
82 }\r
83 return Status;\r
84}\r
85\r
86/**\r
87 Update hash sequence data.\r
88\r
89 @param HashHandle Hash handle.\r
90 @param DataToHash Data to be hashed.\r
91 @param DataToHashLen Data size.\r
92\r
93 @retval EFI_SUCCESS Hash sequence updated.\r
94**/\r
95EFI_STATUS\r
96EFIAPI\r
97HashUpdate (\r
98 IN HASH_HANDLE HashHandle,\r
99 IN VOID *DataToHash,\r
100 IN UINTN DataToHashLen\r
101 )\r
102{\r
103 UINT8 *Buffer;\r
104 UINT64 HashLen;\r
105 TPM2B_MAX_BUFFER HashBuffer;\r
106 EFI_STATUS Status;\r
107\r
108 Buffer = (UINT8 *)(UINTN)DataToHash;\r
109 for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
110\r
111 HashBuffer.size = sizeof(HashBuffer.buffer);\r
112 CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
113 Buffer += sizeof(HashBuffer.buffer);\r
114\r
115 Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
116 if (EFI_ERROR(Status)) {\r
117 return EFI_DEVICE_ERROR;\r
118 }\r
119 }\r
120\r
121 //\r
122 // Last one\r
123 //\r
124 HashBuffer.size = (UINT16)HashLen;\r
125 CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
126 Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
127 if (EFI_ERROR(Status)) {\r
128 return EFI_DEVICE_ERROR;\r
129 }\r
130\r
131 return EFI_SUCCESS;\r
132}\r
133\r
134/**\r
135 Hash sequence complete and extend to PCR.\r
136\r
137 @param HashHandle Hash handle.\r
138 @param PcrIndex PCR to be extended.\r
139 @param DataToHash Data to be hashed.\r
140 @param DataToHashLen Data size.\r
141 @param DigestList Digest list.\r
142\r
143 @retval EFI_SUCCESS Hash sequence complete and DigestList is returned.\r
144**/\r
145EFI_STATUS\r
146EFIAPI\r
147HashCompleteAndExtend (\r
148 IN HASH_HANDLE HashHandle,\r
149 IN TPMI_DH_PCR PcrIndex,\r
150 IN VOID *DataToHash,\r
151 IN UINTN DataToHashLen,\r
152 OUT TPML_DIGEST_VALUES *DigestList\r
153 )\r
154{\r
155 UINT8 *Buffer;\r
156 UINT64 HashLen;\r
157 TPM2B_MAX_BUFFER HashBuffer;\r
158 EFI_STATUS Status;\r
159 TPM_ALG_ID AlgoId;\r
160 TPM2B_DIGEST Result;\r
161\r
162 AlgoId = Tpm2GetAlgoFromHashMask ();\r
163\r
164 Buffer = (UINT8 *)(UINTN)DataToHash;\r
165 for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
166\r
167 HashBuffer.size = sizeof(HashBuffer.buffer);\r
168 CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
169 Buffer += sizeof(HashBuffer.buffer);\r
170\r
171 Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
172 if (EFI_ERROR(Status)) {\r
173 return EFI_DEVICE_ERROR;\r
174 }\r
175 }\r
176\r
177 //\r
178 // Last one\r
179 //\r
180 HashBuffer.size = (UINT16)HashLen;\r
181 CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
182\r
183 ZeroMem(DigestList, sizeof(*DigestList));\r
184 DigestList->count = HASH_COUNT;\r
185\r
186 if (AlgoId == TPM_ALG_NULL) {\r
187 Status = Tpm2EventSequenceComplete (\r
188 PcrIndex,\r
189 (TPMI_DH_OBJECT)HashHandle,\r
190 &HashBuffer,\r
191 DigestList\r
192 );\r
193 } else {\r
194 Status = Tpm2SequenceComplete (\r
195 (TPMI_DH_OBJECT)HashHandle,\r
196 &HashBuffer,\r
197 &Result\r
198 );\r
199 if (EFI_ERROR(Status)) {\r
200 return EFI_DEVICE_ERROR;\r
201 }\r
202\r
203 DigestList->count = 1;\r
204 DigestList->digests[0].hashAlg = AlgoId;\r
205 CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
206 Status = Tpm2PcrExtend (\r
207 PcrIndex,\r
208 DigestList\r
209 );\r
210 }\r
211 if (EFI_ERROR(Status)) {\r
212 return EFI_DEVICE_ERROR;\r
213 }\r
214 return EFI_SUCCESS;\r
215}\r
216\r
217/**\r
218 Hash data and extend to PCR.\r
219\r
220 @param PcrIndex PCR to be extended.\r
221 @param DataToHash Data to be hashed.\r
222 @param DataToHashLen Data size.\r
223 @param DigestList Digest list.\r
224\r
225 @retval EFI_SUCCESS Hash data and DigestList is returned.\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229HashAndExtend (\r
230 IN TPMI_DH_PCR PcrIndex,\r
231 IN VOID *DataToHash,\r
232 IN UINTN DataToHashLen,\r
233 OUT TPML_DIGEST_VALUES *DigestList\r
234 )\r
235{\r
236 EFI_STATUS Status;\r
237 UINT8 *Buffer;\r
238 UINT64 HashLen;\r
239 TPMI_DH_OBJECT SequenceHandle;\r
240 TPM2B_MAX_BUFFER HashBuffer;\r
241 TPM_ALG_ID AlgoId;\r
242 TPM2B_EVENT EventData;\r
243 TPM2B_DIGEST Result;\r
244\r
245 DEBUG((EFI_D_INFO, "\n HashAndExtend Entry \n"));\r
246\r
247 SequenceHandle = 0xFFFFFFFF; // Know bad value\r
248\r
249 AlgoId = Tpm2GetAlgoFromHashMask ();\r
250\r
251 if ((AlgoId == TPM_ALG_NULL) && (DataToHashLen <= sizeof(EventData.buffer))) {\r
252 EventData.size = (UINT16)DataToHashLen;\r
253 CopyMem (EventData.buffer, DataToHash, DataToHashLen);\r
254 Status = Tpm2PcrEvent (PcrIndex, &EventData, DigestList);\r
255 if (EFI_ERROR(Status)) {\r
256 return EFI_DEVICE_ERROR;\r
257 }\r
258 return EFI_SUCCESS;\r
259 }\r
260\r
261 Status = Tpm2HashSequenceStart(AlgoId, &SequenceHandle);\r
262 if (EFI_ERROR(Status)) {\r
263 return EFI_DEVICE_ERROR;\r
264 }\r
265 DEBUG((EFI_D_INFO, "\n Tpm2HashSequenceStart Success \n"));\r
266\r
267 Buffer = (UINT8 *)(UINTN)DataToHash;\r
268 for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
269\r
270 HashBuffer.size = sizeof(HashBuffer.buffer);\r
271 CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
272 Buffer += sizeof(HashBuffer.buffer);\r
273\r
274 Status = Tpm2SequenceUpdate(SequenceHandle, &HashBuffer);\r
275 if (EFI_ERROR(Status)) {\r
276 return EFI_DEVICE_ERROR;\r
277 }\r
278 }\r
279 DEBUG((EFI_D_INFO, "\n Tpm2SequenceUpdate Success \n"));\r
280\r
281 HashBuffer.size = (UINT16)HashLen;\r
282 CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
283\r
284 ZeroMem(DigestList, sizeof(*DigestList));\r
285 DigestList->count = HASH_COUNT;\r
286\r
287 if (AlgoId == TPM_ALG_NULL) {\r
288 Status = Tpm2EventSequenceComplete (\r
289 PcrIndex,\r
290 SequenceHandle,\r
291 &HashBuffer,\r
292 DigestList\r
293 );\r
294 if (EFI_ERROR(Status)) {\r
295 return EFI_DEVICE_ERROR;\r
296 }\r
297 DEBUG((EFI_D_INFO, "\n Tpm2EventSequenceComplete Success \n"));\r
298 } else {\r
299 Status = Tpm2SequenceComplete (\r
300 SequenceHandle,\r
301 &HashBuffer,\r
302 &Result\r
303 );\r
304 if (EFI_ERROR(Status)) {\r
305 return EFI_DEVICE_ERROR;\r
306 }\r
307 DEBUG((EFI_D_INFO, "\n Tpm2SequenceComplete Success \n"));\r
308\r
309 DigestList->count = 1;\r
310 DigestList->digests[0].hashAlg = AlgoId;\r
311 CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
312 Status = Tpm2PcrExtend (\r
313 PcrIndex,\r
314 DigestList\r
315 );\r
316 if (EFI_ERROR(Status)) {\r
317 return EFI_DEVICE_ERROR;\r
318 }\r
319 DEBUG((EFI_D_INFO, "\n Tpm2PcrExtend Success \n"));\r
320 }\r
321\r
322 return EFI_SUCCESS;\r
323}\r
324\r
325/**\r
326 This service register Hash.\r
327\r
328 @param HashInterface Hash interface\r
329\r
330 @retval EFI_SUCCESS This hash interface is registered successfully.\r
331 @retval EFI_UNSUPPORTED System does not support register this interface.\r
332 @retval EFI_ALREADY_STARTED System already register this interface.\r
333**/\r
334EFI_STATUS\r
335EFIAPI\r
336RegisterHashInterfaceLib (\r
337 IN HASH_INTERFACE *HashInterface\r
338 )\r
339{\r
340 return EFI_UNSUPPORTED;\r
341}