mirror of https://github.com/acidanthera/audk.git
258 lines
6.7 KiB
C
258 lines
6.7 KiB
C
/** @file
|
|
TPM Platform Hierarchy configuration library.
|
|
|
|
This library provides functions for customizing the TPM's Platform Hierarchy
|
|
Authorization Value (platformAuth) and Platform Hierarchy Authorization
|
|
Policy (platformPolicy) can be defined through this function.
|
|
|
|
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
Copyright (c) Microsoft Corporation.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
@par Specification Reference:
|
|
https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/RngLib.h>
|
|
#include <Library/Tpm2CommandLib.h>
|
|
#include <Library/Tpm2DeviceLib.h>
|
|
|
|
//
|
|
// The authorization value may be no larger than the digest produced by the hash
|
|
// algorithm used for context integrity.
|
|
//
|
|
|
|
UINT16 mAuthSize;
|
|
|
|
/**
|
|
Generate high-quality entropy source through RDRAND.
|
|
|
|
@param[in] Length Size of the buffer, in bytes, to fill with.
|
|
@param[out] Entropy Pointer to the buffer to store the entropy data.
|
|
|
|
@retval EFI_SUCCESS Entropy generation succeeded.
|
|
@retval EFI_NOT_READY Failed to request random data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RdRandGenerateEntropy (
|
|
IN UINTN Length,
|
|
OUT UINT8 *Entropy
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BlockCount;
|
|
UINT64 Seed[2];
|
|
UINT8 *Ptr;
|
|
|
|
Status = EFI_NOT_READY;
|
|
BlockCount = Length / sizeof (Seed);
|
|
Ptr = (UINT8 *)Entropy;
|
|
|
|
//
|
|
// Generate high-quality seed for DRBG Entropy
|
|
//
|
|
while (BlockCount > 0) {
|
|
Status = GetRandomNumber128 (Seed);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
CopyMem (Ptr, Seed, sizeof (Seed));
|
|
|
|
BlockCount--;
|
|
Ptr = Ptr + sizeof (Seed);
|
|
}
|
|
|
|
//
|
|
// Populate the remained data as request.
|
|
//
|
|
Status = GetRandomNumber128 (Seed);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
CopyMem (Ptr, Seed, (Length % sizeof (Seed)));
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This function returns the maximum size of TPM2B_AUTH; this structure is used for an authorization value
|
|
and limits an authValue to being no larger than the largest digest produced by a TPM.
|
|
|
|
@param[out] AuthSize Tpm2 Auth size
|
|
|
|
@retval EFI_SUCCESS Auth size returned.
|
|
@retval EFI_DEVICE_ERROR Can not return platform auth due to device error.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GetAuthSize (
|
|
OUT UINT16 *AuthSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPML_PCR_SELECTION Pcrs;
|
|
UINTN Index;
|
|
UINT16 DigestSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
while (mAuthSize == 0) {
|
|
mAuthSize = SHA1_DIGEST_SIZE;
|
|
ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
|
|
Status = Tpm2GetCapabilityPcrs (&Pcrs);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));
|
|
break;
|
|
}
|
|
|
|
DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - %08x\n", Pcrs.count));
|
|
|
|
for (Index = 0; Index < Pcrs.count; Index++) {
|
|
DEBUG ((DEBUG_ERROR, "alg - %x\n", Pcrs.pcrSelections[Index].hash));
|
|
|
|
switch (Pcrs.pcrSelections[Index].hash) {
|
|
case TPM_ALG_SHA1:
|
|
DigestSize = SHA1_DIGEST_SIZE;
|
|
break;
|
|
case TPM_ALG_SHA256:
|
|
DigestSize = SHA256_DIGEST_SIZE;
|
|
break;
|
|
case TPM_ALG_SHA384:
|
|
DigestSize = SHA384_DIGEST_SIZE;
|
|
break;
|
|
case TPM_ALG_SHA512:
|
|
DigestSize = SHA512_DIGEST_SIZE;
|
|
break;
|
|
case TPM_ALG_SM3_256:
|
|
DigestSize = SM3_256_DIGEST_SIZE;
|
|
break;
|
|
default:
|
|
DigestSize = SHA1_DIGEST_SIZE;
|
|
break;
|
|
}
|
|
|
|
if (DigestSize > mAuthSize) {
|
|
mAuthSize = DigestSize;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
*AuthSize = mAuthSize;
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Set PlatformAuth to random value.
|
|
**/
|
|
VOID
|
|
RandomizePlatformAuth (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 AuthSize;
|
|
TPM2B_AUTH NewPlatformAuth;
|
|
|
|
//
|
|
// Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null
|
|
//
|
|
|
|
GetAuthSize (&AuthSize);
|
|
|
|
NewPlatformAuth.size = AuthSize;
|
|
|
|
//
|
|
// Create the random bytes in the destination buffer
|
|
//
|
|
|
|
RdRandGenerateEntropy (NewPlatformAuth.size, NewPlatformAuth.buffer);
|
|
|
|
//
|
|
// Send Tpm2HierarchyChangeAuth command with the new Auth value
|
|
//
|
|
Status = Tpm2HierarchyChangeAuth (TPM_RH_PLATFORM, NULL, &NewPlatformAuth);
|
|
DEBUG ((DEBUG_INFO, "Tpm2HierarchyChangeAuth Result: - %r\n", Status));
|
|
ZeroMem (NewPlatformAuth.buffer, AuthSize);
|
|
}
|
|
|
|
/**
|
|
Disable the TPM platform hierarchy.
|
|
|
|
@retval EFI_SUCCESS The TPM was disabled successfully.
|
|
@retval Others An error occurred attempting to disable the TPM platform hierarchy.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DisableTpmPlatformHierarchy (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
// Make sure that we have use of the TPM.
|
|
Status = Tpm2RequestUseTpm ();
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "%a:%a() - Tpm2RequestUseTpm Failed! %r\n", gEfiCallerBaseName, __func__, Status));
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
// Let's do what we can to shut down the hierarchies.
|
|
|
|
// Disable the PH NV.
|
|
// IMPORTANT NOTE: We *should* be able to disable the PH NV here, but TPM parts have
|
|
// been known to store the EK cert in the PH NV. If we disable it, the
|
|
// EK cert will be unreadable.
|
|
|
|
// Disable the PH.
|
|
Status = Tpm2HierarchyControl (
|
|
TPM_RH_PLATFORM, // AuthHandle
|
|
NULL, // AuthSession
|
|
TPM_RH_PLATFORM, // Hierarchy
|
|
NO // State
|
|
);
|
|
DEBUG ((DEBUG_VERBOSE, "%a:%a() - Disable PH = %r\n", gEfiCallerBaseName, __func__, Status));
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "%a:%a() - Disable PH Failed! %r\n", gEfiCallerBaseName, __func__, Status));
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This service defines the configuration of the Platform Hierarchy Authorization Value (platformAuth)
|
|
and Platform Hierarchy Authorization Policy (platformPolicy).
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ConfigureTpmPlatformHierarchy (
|
|
)
|
|
{
|
|
if (PcdGetBool (PcdRandomizePlatformHierarchy)) {
|
|
//
|
|
// Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null
|
|
//
|
|
RandomizePlatformAuth ();
|
|
} else {
|
|
//
|
|
// Disable the hierarchy entirely (do not randomize it)
|
|
//
|
|
DisableTpmPlatformHierarchy ();
|
|
}
|
|
}
|