1 /** @file 2 Implement TPM2 help. 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 typedef struct { 23 TPMI_ALG_HASH HashAlgo; 24 UINT16 HashSize; 25 UINT32 HashMask; 26 } INTERNAL_HASH_INFO; 27 28 STATIC INTERNAL_HASH_INFO mHashInfo[] = { 29 {TPM_ALG_SHA1, SHA1_DIGEST_SIZE, HASH_ALG_SHA1}, 30 {TPM_ALG_SHA256, SHA256_DIGEST_SIZE, HASH_ALG_SHA256}, 31 {TPM_ALG_SM3_256, SM3_256_DIGEST_SIZE, HASH_ALG_SM3_256}, 32 {TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384}, 33 {TPM_ALG_SHA512, SHA512_DIGEST_SIZE, HASH_ALG_SHA512}, 34 }; 35 36 /** 37 Return size of digest. 38 39 @param[in] HashAlgo Hash algorithm 40 41 @return size of digest 42 **/ 43 UINT16 44 EFIAPI 45 GetHashSizeFromAlgo ( 46 IN TPMI_ALG_HASH HashAlgo 47 ) 48 { 49 UINTN Index; 50 51 for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) { 52 if (mHashInfo[Index].HashAlgo == HashAlgo) { 53 return mHashInfo[Index].HashSize; 54 } 55 } 56 return 0; 57 } 58 59 /** 60 Get hash mask from algorithm. 61 62 @param[in] HashAlgo Hash algorithm 63 64 @return Hash mask 65 **/ 66 UINT32 67 EFIAPI 68 GetHashMaskFromAlgo ( 69 IN TPMI_ALG_HASH HashAlgo 70 ) 71 { 72 UINTN Index; 73 74 for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) { 75 if (mHashInfo[Index].HashAlgo == HashAlgo) { 76 return mHashInfo[Index].HashMask; 77 } 78 } 79 return 0; 80 } 81 82 /** 83 Copy AuthSessionIn to TPM2 command buffer. 84 85 @param [in] AuthSessionIn Input AuthSession data 86 @param [out] AuthSessionOut Output AuthSession data in TPM2 command buffer 87 88 @return AuthSession size 89 **/ 90 UINT32 91 EFIAPI 92 CopyAuthSessionCommand ( 93 IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL 94 OUT UINT8 *AuthSessionOut 95 ) 96 { 97 UINT8 *Buffer; 98 99 Buffer = (UINT8 *)AuthSessionOut; 100 101 // 102 // Add in Auth session 103 // 104 if (AuthSessionIn != NULL) { 105 // sessionHandle 106 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle)); 107 Buffer += sizeof(UINT32); 108 109 // nonce 110 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size)); 111 Buffer += sizeof(UINT16); 112 113 CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size); 114 Buffer += AuthSessionIn->nonce.size; 115 116 // sessionAttributes 117 *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes; 118 Buffer++; 119 120 // hmac 121 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size)); 122 Buffer += sizeof(UINT16); 123 124 CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size); 125 Buffer += AuthSessionIn->hmac.size; 126 } else { 127 // sessionHandle 128 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW)); 129 Buffer += sizeof(UINT32); 130 131 // nonce = nullNonce 132 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0)); 133 Buffer += sizeof(UINT16); 134 135 // sessionAttributes = 0 136 *(UINT8 *)Buffer = 0x00; 137 Buffer++; 138 139 // hmac = nullAuth 140 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0)); 141 Buffer += sizeof(UINT16); 142 } 143 144 return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionOut); 145 } 146 147 /** 148 Copy AuthSessionIn from TPM2 response buffer. 149 150 @param [in] AuthSessionIn Input AuthSession data in TPM2 response buffer 151 @param [out] AuthSessionOut Output AuthSession data 152 153 @return AuthSession size 154 **/ 155 UINT32 156 EFIAPI 157 CopyAuthSessionResponse ( 158 IN UINT8 *AuthSessionIn, 159 OUT TPMS_AUTH_RESPONSE *AuthSessionOut OPTIONAL 160 ) 161 { 162 UINT8 *Buffer; 163 TPMS_AUTH_RESPONSE LocalAuthSessionOut; 164 165 if (AuthSessionOut == NULL) { 166 AuthSessionOut = &LocalAuthSessionOut; 167 } 168 169 Buffer = (UINT8 *)AuthSessionIn; 170 171 // nonce 172 AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); 173 Buffer += sizeof(UINT16); 174 175 CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size); 176 Buffer += AuthSessionOut->nonce.size; 177 178 // sessionAttributes 179 *(UINT8 *)&AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer; 180 Buffer++; 181 182 // hmac 183 AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); 184 Buffer += sizeof(UINT16); 185 186 CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size); 187 Buffer += AuthSessionOut->hmac.size; 188 189 return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionIn); 190 } 191 192 /** 193 Return if hash alg is supported in HashAlgorithmMask. 194 195 @param HashAlg Hash algorithm to be checked. 196 @param HashAlgorithmMask Bitfield of allowed hash algorithms. 197 198 @retval TRUE Hash algorithm is supported. 199 @retval FALSE Hash algorithm is not supported. 200 **/ 201 BOOLEAN 202 EFIAPI 203 IsHashAlgSupportedInHashAlgorithmMask( 204 IN TPMI_ALG_HASH HashAlg, 205 IN UINT32 HashAlgorithmMask 206 ) 207 { 208 switch (HashAlg) { 209 case TPM_ALG_SHA1: 210 if ((HashAlgorithmMask & HASH_ALG_SHA1) != 0) { 211 return TRUE; 212 } 213 break; 214 case TPM_ALG_SHA256: 215 if ((HashAlgorithmMask & HASH_ALG_SHA256) != 0) { 216 return TRUE; 217 } 218 break; 219 case TPM_ALG_SHA384: 220 if ((HashAlgorithmMask & HASH_ALG_SHA384) != 0) { 221 return TRUE; 222 } 223 break; 224 case TPM_ALG_SHA512: 225 if ((HashAlgorithmMask & HASH_ALG_SHA512) != 0) { 226 return TRUE; 227 } 228 break; 229 case TPM_ALG_SM3_256: 230 if ((HashAlgorithmMask & HASH_ALG_SM3_256) != 0) { 231 return TRUE; 232 } 233 break; 234 } 235 236 return FALSE; 237 } 238 239 /** 240 Copy TPML_DIGEST_VALUES into a buffer 241 242 @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary. 243 @param[in] DigestList TPML_DIGEST_VALUES to be copied. 244 @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy. 245 246 @return The end of buffer to hold TPML_DIGEST_VALUES. 247 **/ 248 VOID * 249 EFIAPI 250 CopyDigestListToBuffer ( 251 IN OUT VOID *Buffer, 252 IN TPML_DIGEST_VALUES *DigestList, 253 IN UINT32 HashAlgorithmMask 254 ) 255 { 256 UINTN Index; 257 UINT16 DigestSize; 258 UINT32 DigestListCount; 259 UINT32 *DigestListCountPtr; 260 261 DigestListCountPtr = (UINT32 *) Buffer; 262 DigestListCount = 0; 263 Buffer = (UINT8 *)Buffer + sizeof(DigestList->count); 264 for (Index = 0; Index < DigestList->count; Index++) { 265 if (!IsHashAlgSupportedInHashAlgorithmMask(DigestList->digests[Index].hashAlg, HashAlgorithmMask)) { 266 DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); 267 continue; 268 } 269 CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg)); 270 Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg); 271 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); 272 CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize); 273 Buffer = (UINT8 *)Buffer + DigestSize; 274 DigestListCount++; 275 } 276 WriteUnaligned32 (DigestListCountPtr, DigestListCount); 277 278 return Buffer; 279 } 280 281 /** 282 Get TPML_DIGEST_VALUES data size. 283 284 @param[in] DigestList TPML_DIGEST_VALUES data. 285 286 @return TPML_DIGEST_VALUES data size. 287 **/ 288 UINT32 289 EFIAPI 290 GetDigestListSize ( 291 IN TPML_DIGEST_VALUES *DigestList 292 ) 293 { 294 UINTN Index; 295 UINT16 DigestSize; 296 UINT32 TotalSize; 297 298 TotalSize = sizeof(DigestList->count); 299 for (Index = 0; Index < DigestList->count; Index++) { 300 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); 301 TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize; 302 } 303 304 return TotalSize; 305 } 306 307 /** 308 This function get digest from digest list. 309 310 @param[in] HashAlg Digest algorithm 311 @param[in] DigestList Digest list 312 @param[out] Digest Digest 313 314 @retval EFI_SUCCESS Digest is found and returned. 315 @retval EFI_NOT_FOUND Digest is not found. 316 **/ 317 EFI_STATUS 318 EFIAPI 319 GetDigestFromDigestList ( 320 IN TPMI_ALG_HASH HashAlg, 321 IN TPML_DIGEST_VALUES *DigestList, 322 OUT VOID *Digest 323 ) 324 { 325 UINTN Index; 326 UINT16 DigestSize; 327 328 DigestSize = GetHashSizeFromAlgo (HashAlg); 329 for (Index = 0; Index < DigestList->count; Index++) { 330 if (DigestList->digests[Index].hashAlg == HashAlg) { 331 CopyMem ( 332 Digest, 333 &DigestList->digests[Index].digest, 334 DigestSize 335 ); 336 return EFI_SUCCESS; 337 } 338 } 339 340 return EFI_NOT_FOUND; 341 } 342