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