blob: 81a5900b927607cf79154aea37c40c04d6d6ba0b [file] [log] [blame]
/** @file
This file connects Tcg TPM reference code's platform specific functions
to correspond functions in PlatformTpmLib.
about each "_plat__XXX" interfaces in TPM reference libraries, see:
- https://github.com/TrustedComputingGroup/TPM/blob/main/TPMCmd/Platform/src
When TPM reference library is build, it links with PlatformTpmLib
which have correspondant interfaces with "_plat_XXX" to "PlatformTpmLibXXX"
By this, when TPM reference library calls "_plat_XXX",
it calls "_plat_XXX" in this file and finally this file calls
"PlatformTpmLibXXX" implemented in PlatformTpmLib.
That's why this doesn't follow edk2 coding style
But remain as it is including comment style in TPM reference library
for clarification.
Of course, this doesn't defines all _plat_XXX interfaces in TPM
reference library because interfaces are enough with default implementation
in TPM reference library.
Copyright (c) 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
typedef unsigned char uint8_t;
typedef int BOOL;
#include <Uefi/UefiBaseType.h>
#include <Library/BaseLib.h>
#include <Library/PlatformTpmLib.h>
#include <TpmConfiguration/TpmBuildSwitches.h>
#include <CompilerDependencies.h>
#include <ExecCommand_fp.h>
#include <platform_interface/tpm_to_platform_interface.h>
/**
This function used to generate Endorsement Seed when
first initailization of TPM.
@param [in] Size Size of endorsement seed
@param [out] EndorsementSeed Endorsement Seed.
**/
LIB_EXPORT void
_plat__GetEPS (
UINT16 Size,
uint8_t *EndorsementSeed
)
{
PlatformTpmLibGetEPS (Size, EndorsementSeed);
}
/**
This function sets current system clock time as t0 for counting TPM time.
This function is called at a power on event to reset the clock. When the clock
is reset, the indication that the clock was stopped is also set.
**/
LIB_EXPORT void
_plat__TimerReset (
void
)
{
PlatformTpmLibTimerReset ();
}
/**
This function should be called in order to simulate the restart of the timer
should it be stopped while power is still applied.
**/
LIB_EXPORT void
_plat__TimerRestart (
void
)
{
PlatformTpmLibTimerRestart ();
}
/**
This is another, probably futile, attempt to define a portable function
that will return a 64-bit clock value that has mSec resolution.
**/
LIB_EXPORT uint64_t
_plat__RealTime (
void
)
{
return PlatformTpmLibRealTime ();
}
/**
This function provides access to the tick timer of the platform. The TPM code
uses this value to drive the TPM Clock.
The tick timer is supposed to run when power is applied to the device. This timer
should not be reset by time events including _TPM_Init. It should only be reset
when TPM power is re-applied.
If the TPM is run in a protected environment, that environment may provide the
tick time to the TPM as long as the time provided by the environment is not
allowed to go backwards. If the time provided by the system can go backwards
during a power discontinuity, then the _plat__Signal_PowerOn should call
**/
LIB_EXPORT uint64_t
_plat__TimerRead (
void
)
{
return PlatformTpmLibTimerRead ();
}
/**
This function is used to interrogate the flag indicating if the tick timer has
been reset.
If the resetFlag parameter is SET, then the flag will be CLEAR before the
function returns.
**/
LIB_EXPORT int
_plat__TimerWasReset (
void
)
{
return PlatformTpmLibTimerWasReset ();
}
/**
This function is used to interrogate the flag indicating if the tick timer has
been stopped. If so, this is typically a reason to roll the nonce.
This function will CLEAR the s_timerStopped flag before returning. This provides
functionality that is similar to status register that is cleared when read. This
is the model used here because it is the one that has the most impact on the TPM
code as the flag can only be accessed by one entity in the TPM. Any other
implementation of the hardware can be made to look like a read-once register.
**/
LIB_EXPORT BOOL
_plat__TimerWasStopped (
void
)
{
return (BOOL)PlatformTpmLibTimerWasStopped ();
}
/**
ClockRateAdjust uses predefined signal values and encapsulates the platform
specifics regarding the number of ticks the underlying clock is running at.
The adjustment must be one of these values. A COARSE adjustment is 1%, MEDIUM
is 0.1%, and FINE is the smallest amount supported by the platform. The
total (cumulative) adjustment is limited to ~15% total. Attempts to adjust
the clock further are silently ignored as are any invalid values. These
values are defined here to insulate them from spec changes and to avoid
needing visibility to the doc-generated structure headers.
@param [in] Adjust The adjust number.
**/
LIB_EXPORT void
_plat__ClockRateAdjust (
_plat__ClockAdjustStep adjust
)
{
PlatformTpmLibClockAdjustRate (adjust);
}
/**
_plat__GetEntropy()
This function is used to get available hardware entropy. In a hardware
implementation of this function, there would be no call to the system
to get entropy.
@param [out] Entropy
@param [in] Amount amount reuqested.
@return < 0 Failed to generate entropy
@return >= 0 The returned amount of entropy (bytes)
**/
LIB_EXPORT int32_t
_plat__GetEntropy (
unsigned char *entropy, // output buffer
uint32_t amount // amount requested
)
{
return PlatformTpmLibGetEntropy (entropy, amount);
}
/**
Enable NV memory.
the NV state would be read in, decrypted and integrity checked if needs.
The recovery from an integrity failure depends on where the error occurred. It
it was in the state that is discarded by TPM Reset, then the error is
recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode.
@param [in] PlatParameter Platform parameter to enable NV storage
@param [in] ParamSize
@return 0 if success
@return > 0 if receive recoverable error
@return < 0 if unrecoverable error
**/
LIB_EXPORT int
_plat__NVEnable (
void *platParameter, // IN: platform specific parameters
size_t paramSize
)
{
return PlatformTpmLibNVEnable (platParameter, paramSize);
}
/**
Disable NV memory.
**/
LIB_EXPORT void
_plat__NVDisable (
VOID
)
{
PlatformTpmLibNVDisable ();
}
/**
Check if NV is available
@return 0 NV is available
@return 1 NV is not available due to write failure
@return 2 NV is not available due to rate limit
**/
LIB_EXPORT int
_plat__GetNvReadyState (
void
)
{
return PlatformTpmLibGetNvReadyState ();
}
/**
Read a chunk of NV memory
@param [in] StartOffset Read start offset
@param [in] Size Size to read
@param [out] Data Data buffer
@return 1 Success to read
@return 0 Failed to read
**/
LIB_EXPORT int
_plat__NvMemoryRead (
unsigned int startOffset, // IN: read start
unsigned int size, // IN: size of bytes to read
void *data // OUT: data buffer
)
{
return PlatformTpmLibNvMemoryRead (
startOffset,
size,
data
);
}
/**
This function checks to see if the NV is different from the test value
so that NV will not be written if it has not changed.
@param [in] StartOffset Start offset to compare
@param [in] Size Size for compare
@param [in] Data Data to be compared
@return NV_HAS_CHANGED(1) the NV location is different from the test value
@return NV_IS_SAME(0) the NV location is the same as the test value
@return NV_INVALID_LOCATION(-1) the NV location is invalid; also triggers failure mode
**/
LIB_EXPORT int
_plat__NvGetChangedStatus (
unsigned int startOffset, // IN: read start
unsigned int size, // IN: size of bytes to read
void *data // IN: data buffer
)
{
return PlatformTpmLibNvGetChangedStatus (
startOffset,
size,
data
);
}
/**
_plat__NvMemoryWrite()
This function is used to update NV memory. The "write" is to a memory copy of
NV. At the end of the current command, any changes are written to
the actual NV memory.
NOTE: A useful optimization would be for this code to compare the current
contents of NV with the local copy and note the blocks that have changed. Then
only write those blocks when _plat__NvCommit() is called.
@param [in] StartOffset Start Offset to write
@param [in] Size Size to wrrite
@param [in] Data Data
@return 0 Failed to write
@return 1 Success to write
**/
LIB_EXPORT int
_plat__NvMemoryWrite (
unsigned int startOffset, // IN: write start
unsigned int size, // IN: size of bytes to write
void *data // OUT: data buffer
)
{
return PlatformTpmLibNvMemoryWrite (
startOffset,
size,
data
);
}
/**
Function is used to set a range of NV memory bytes to an implementation-dependent
value. The value represents the erase state of the memory.
@param [in] StartOffset Start offset to clear
@param [in] SIze Size to be clear
@return 0 Failed to clear
@return 1 Success
**/
LIB_EXPORT int
_plat__NvMemoryClear (
unsigned int start, // IN: clear start
unsigned int size // IN: number of bytes to clear
)
{
return PlatformTpmLibNvMemoryClear (
start,
size
);
}
/**
Move a chunk of NV memory from source to destination
This function should ensure that if there overlap, the original data is
copied before it is written
@param [in] SourceOffset Source offset to move
@param [in] DestOffset Destination offset to move
@param [in] Size Size to be moved
@return 0 Failed to move
@return 1 Success
**/
LIB_EXPORT int
_plat__NvMemoryMove (
unsigned int sourceOffset, // IN: source offset
unsigned int destOffset, // IN: destination offset
unsigned int size // IN: size of data being moved
)
{
return PlatformTpmLibNvMemoryMove (
sourceOffset,
destOffset,
size
);
}
/**
This function writes the local copy of NV to NV for permanent store.
It will write TPM_NV_MEMORY_SIZE bytes to NV.
@return 0 NV write success
@return non-0 NV write fail
**/
LIB_EXPORT int
_plat__NvCommit (
void
)
{
return PlatformTpmLibNvCommit ();
}
/**
Set the current NV state to available.
This function is for testing purpose only.
It is not part of the platform NV logic
**/
LIB_EXPORT void
_plat__SetNvAvail (
void
)
{
PlatformTpmLibSetNvAvail ();
}
/**
Set the current NV state to unavailable.
This function is for testing purpose only.
It is not part of the platform NV logic
**/
LIB_EXPORT void
_plat__ClearNvAvail (
void
)
{
PlatformTpmLibClearNvAvail ();
}
/**
_plat__NVNeedsManufacture()
This function checks whether TPM's NV state needs to be manufactured
**/
LIB_EXPORT int
_plat__NVNeedsManufacture (
void
)
{
return (int)PlatformTpmLibNVNeedsManufacture ();
}
/**
Excecute TPM command
@param[in] requestSize command buffer size
@param[in] request command buffer
@param[inout] responseSize buffer size
@param[inout] response buffer
**/
LIB_EXPORT void
_plat__RunCommand (
uint32_t requestSize,
unsigned char *request,
uint32_t *responseSize,
unsigned char **response
)
{
ExecuteCommand (
requestSize,
request,
responseSize,
response
);
}
/**
This function is used to access the platform-specific unique value.
This function places the unique value in the provided buffer ('b')
and returns the number of bytes transferred. The function will not
copy more data than 'bSize'.
NOTE: If a platform unique value has unequal distribution of uniqueness
and 'bSize' is smaller than the size of the unique value, the 'bSize'
portion with the most uniqueness should be returned.
@param [in] Which if == 0, Copy unique value from start
otherwise, copy from end
@param [in] Size Size of Buffer
@param [out] Buffer
@return Size of unique value.
**/
LIB_EXPORT uint32_t
_plat__GetUnique (
uint32_t which, // authorities (0) or details
uint32_t bSize, // size of the buffer
unsigned char *b // output buffer
)
{
return PlatformTpmLibGetUnique (
which,
bSize,
b
);
}
/**
return the 4 character Manufacturer Capability code.
This should come from the platform library since
that is provided by the manufacturer.
@return Manufacturer capability Code.
**/
LIB_EXPORT uint32_t
_plat__GetManufacturerCapabilityCode (
void
)
{
return PlatformTpmLibGetManufacturerCapabilityCode ();
}
/**
_plat__GetVendorCapabilityCode()
return the 4 character VendorStrings for Capabilities.
Index is ONE-BASED, and may be in the range [1,4] inclusive.
Any other index returns all zeros. The return value will be interpreted
as an array of 4 ASCII characters (with no null terminator).
@param[in] Index index
@return Vendor specific capability code.
**/
LIB_EXPORT uint32_t
_plat__GetVendorCapabilityCode (
int index
)
{
return PlatformTpmLibGetVendorCapabilityCode (index);
}
/**
return the most-significant 32-bits of the TPM Firmware Version
@return High 32-bits of TPM Firmware Version.
**/
LIB_EXPORT uint32_t
_plat__GetTpmFirmwareVersionHigh (
void
)
{
return PlatformTpmLibGetTpmFirmwareVersionHigh ();
}
/**
return the least-significant 32-bits of the TPM Firmware Version
@return Low 32-bits of TPM Firmware Version.
**/
LIB_EXPORT uint32_t
_plat__GetTpmFirmwareVersionLow (
void
)
{
return PlatformTpmLibGetTpmFirmwareVersionLow ();
}
/**
return the TPM Firmware current SVN.
@return current SVN.
**/
LIB_EXPORT uint16_t
_plat__GetTpmFirmwareSvn (
void
)
{
return PlatformTpmLibGetTpmFirmwareSvn ();
}
/**
return the TPM Firmware maximum SVN.
@return Maximum SVN.
**/
LIB_EXPORT uint16_t
_plat__GetTpmFirmwareMaxSvn (
void
)
{
return PlatformTpmLibGetTpmFirmwareMaxSvn ();
}
/**
return the TPM Firmware SVN Secret value associated with SVN
@param[in] Svn Svn
@param[in] SecretBufferSize Secret Buffer Size
@param[out] SecretBuffer Secret Buffer
@param[out] SecretSize Secret Svn Size
@return 0 Success
@return < 0 Error
**/
LIB_EXPORT int
_plat__GetTpmFirmwareSvnSecret (
uint16_t svn,
uint16_t secret_buf_size,
uint8_t *secret_buf,
uint16_t *secret_size
)
{
return PlatformTpmLibGetTpmFirmwareSvnSecret (
svn,
secret_buf_size,
secret_buf,
secret_size
);
}
/**
return the TPM Firmware Secret value associated with SVN
@param[in] SecretBufferSize Secret Buffer Size
@param[out] SecretBuffer Secret Buffer
@param[out] SecretSize Secret Svn Size
@return 0 Success
@return < 0 Error
**/
LIB_EXPORT int
_plat__GetTpmFirmwareSecret (
uint16_t secret_buf_size,
uint8_t *secret_buf,
uint16_t *secret_size
)
{
return PlatformTpmLibGetTpmFirmwareSecret (
secret_buf_size,
secret_buf,
secret_size
);
}
/**
This function allows the platform to provide a small amount of data to be
stored as part of the TPM's PERSISTENT_DATA structure during manufacture.
Of course the platform can store data separately as well,
but this allows a simple platform implementation to store
a few bytes of data without implementing a multi-layer storage system.
This function is called on manufacture and CLEAR.
The buffer will contain the last value provided
to the Core library.
@param[out] PlatformPersistentData Platform data.
@param[in] Size Size of PlatformPersistentData.
**/
LIB_EXPORT void
_plat__GetPlatformManufactureData (
uint8_t *pPlatformPersistentData,
uint32_t bufferSize
)
{
return PlatformTpmLibGetPlatformManufactureData (
pPlatformPersistentData,
bufferSize
);
}
/**
Reset platform specific failure data.
**/
void
_plat_internal_resetFailureData (
void
)
{
return PlatformTpmLibInternalResetFailureData ();
}
/**
Check whether platform is in the failure mode.
**/
LIB_EXPORT BOOL
_plat__InFailureMode (
void
)
{
return (BOOL)PlatformTpmLibInFailureMode ();
}
/**
A function for the TPM to call the platform to indicate the
TPM code has detected a failure.
**/
LIB_EXPORT NORETURN void
_plat__Fail (
const char *function,
int line,
uint64_t locationCode,
int failureCode
)
{
PlatformTpmLibFail (function, line, locationCode, failureCode);
/*
* for NORETURN
*/
while (1) {
}
}
/**
Get last failure code.
@return Last failure code.
**/
LIB_EXPORT UINT32
_plat__GetFailureCode (
void
)
{
return PlatformTpmLibGetFailureCode ();
}
/**
_plat__GetFailureLocation()
Get last failure location.
@return Last failure location code.
**/
LIB_EXPORT uint64_t
_plat__GetFailureLocation (
void
)
{
return PlatformTpmLibGetFailureLocation ();
}
/**
Get last function name where failed.
@return Last function name where failed.
**/
LIB_EXPORT const char *
_plat__GetFailureFunctionName (
void
)
{
return PlatformTpmLibGetFailureFunctionName ();
}
/**
Get last failure line.
@return Last line number where failed.
**/
LIB_EXPORT uint32_t
_plat__GetFailureLine (
void
)
{
return PlatformTpmLibGetFailureLine ();
}
/**
return the Platform TPM type.
@return TPM type.
**/
LIB_EXPORT uint32_t
_plat__GetVendorTpmType (
void
)
{
return PlatformTpmLibGetVendorTpmType ();
}
/**
return TPM spec information.
This is copied from TPM/TPMCmd/Platform/src/VendorInfo.c
@param[out] returnData Spec information.
**/
LIB_EXPORT void
_plat_GetSpecCapabilityValue (
SPEC_CAPABILITY_VALUE *returnData
)
{
// clang-format off
// this is on the title page of part1 of the TPM spec
returnData->tpmSpecLevel = 0;
// these come from part2 of the TPM spec
returnData->tpmSpecVersion = 184;
returnData->tpmSpecYear = 2025;
returnData->tpmSpecDayOfYear = 79; // March 20
// these come from the PC Client Platform TPM Profile Specification
returnData->platformFamily = 1;
returnData->platfromLevel = 0;
// The platform spec version is recorded such that 0x00000101 means version 1.01
// Note this differs from some TPM/TCG specifications, but matches the behavior of Windows.
// more recent TCG specs have discontinued using this field, but Windows displays it, so we
// retain it using the historical encoding.
returnData->platformRevision = 0x105;
returnData->platformYear = 0;
returnData->platformDayOfYear = 0;
// clang-format on
return;
}
/**
TpmBuildSwitch.h which includes in tpm_to_platform_interface.h
defines its own DEBUG macro to compile TPM.
So, undef DEBUG macro defined by TpmBuildSwitch.h
and use DEBUG macro defined in DebugLib.h
**/
#undef DEBUG
#include <Library/DebugLib.h>
#if CERTIFYX509_DEBUG
/**
This function opens the file used to hold the debug data.
@retval 0 Success
@retval != 0 Error
**/
INT32
EFIAPI
DebugFileInit (
VOID
)
{
return 0;
}
/**
Dump Buffer
@param[in] size Size of buf
@param[in] buf Buffer
@param[in] identifier Print identifier
**/
VOID
EFIAPI
DebugDumpBuffer (
IN INT32 size,
IN unsigned char *buf,
IN CONST CHAR8 *identifier
)
{
INT32 Idx;
DEBUG ((DEBUG_INFO, "%a\n", identifier));
for (Idx = 0; Idx < size; Idx++) {
if (((Idx % 16) == 0) && (Idx != 0)) {
DEBUG ((DEBUG_INFO, "\n"));
}
DEBUG ((DEBUG_INFO, "%02x\n", buf[Idx]));
}
if ((size % 16) != 0) {
DEBUG ((DEBUG_INFO, "\n"));
}
}
#endif // CERTIFYX509_DEBUG