diff options
Diffstat (limited to 'src/tpm2/ACT_spt.c')
-rw-r--r-- | src/tpm2/ACT_spt.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/src/tpm2/ACT_spt.c b/src/tpm2/ACT_spt.c new file mode 100644 index 0000000..5b19c85 --- /dev/null +++ b/src/tpm2/ACT_spt.c @@ -0,0 +1,317 @@ +/********************************************************************************/ +/* */ +/* ACT Command Support */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: Object_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp. and others, 2016 - 2020 */ +/* */ +/********************************************************************************/ + +/* 7.8 ACT Support (ACT_spt.c) */ +/* 7.8.1 Introduction */ +/* This code implements the ACT update code. It does not use a mutex. This code uses a platform + service (_plat__ACT_UpdateCounter()) that returns false if the update is not accepted. If this + occurs, then TPM_RC_RETRY should be sent to the caller so that they can retry the operation + later. The implementation of this is platform dependent but the reference uses a simple flag to + indicate that an update is pending and the only process that can clear that flag is the process + that does the actual update. */ + +/* 7.8.2 Includes */ + +#include "Tpm.h" +#include "ACT_spt_fp.h" +#include "Platform_fp.h" +#include "PlatformACT_fp.h" /* added kgold */ + +/* 7.8.3 Functions */ +/* 7.8.3.1 _ActResume() */ +/* This function does the resume processing for an ACT. It updates the saved count and turns + signaling back on if necessary. */ +#ifndef __ACT_DISABLED // libtpms added +static void +_ActResume( + UINT32 act, //IN: the act number + ACT_STATE *actData //IN: pointer to the saved ACT data + ) +{ + // If the act was non-zero, then restore the counter value. + if(actData->remaining > 0) + _plat__ACT_UpdateCounter(act, actData->remaining); + // if the counter was zero and the ACT signaling, enable the signaling. + else if(go.signaledACT & (1 << act)) + _plat__ACT_SetSignaled(act, TRUE); +} +#endif // libtpms added +/* 7.8.3.2 ActStartup() */ +/* This function is called by TPM2_Startup() to initialize the ACT counter values. */ +BOOL +ActStartup( + STARTUP_TYPE type + ) +{ + // Reset all the ACT hardware + _plat__ACT_Initialize(); + + // If this not a cold start, copy all the current 'signaled' settings to + // 'preservedSignaled'. +#ifndef __ACT_DISABLED // libtpms added + if (g_powerWasLost) + go.preservedSignaled = 0; + else + go.preservedSignaled |= go.signaledACT; +#endif // libtpms added + + // For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output + // de-asserted. + if(type != SU_RESUME) + { +#ifndef __ACT_DISABLED // libtpms added + go.signaledACT = 0; +#endif // libtpms added +#define CLEAR_ACT_POLICY(N) \ + go.ACT_##N.hashAlg = TPM_ALG_NULL; \ + go.ACT_##N.authPolicy.b.size = 0; + + FOR_EACH_ACT(CLEAR_ACT_POLICY) + + } + else + { + // Resume each of the implemented ACT +#define RESUME_ACT(N) _ActResume(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(RESUME_ACT) + } + // set no ACT updated since last startup. This is to enable the halving of the + // timeout value + s_ActUpdated = 0; + _plat__ACT_EnableTicks(TRUE); + return TRUE; +} +/* 7.8.3.3 _ActSaveState() */ +/* Get the counter state and the signaled state for an ACT. If the ACT has not been updated since + the last time it was saved, then divide the count by 2. */ +#ifndef __ACT_DISABLED // libtpms added +static void +_ActSaveState( + UINT32 act, + P_ACT_STATE actData + ) +{ + actData->remaining = _plat__ACT_GetRemaining(act); + // If the ACT hasn't been updated since the last startup, then it should be + // be halved. + if((s_ActUpdated & (1 << act)) == 0) + { + // Don't halve if the count is set to max or if halving would make it zero + if((actData->remaining != UINT32_MAX) && (actData->remaining > 1)) + actData->remaining /= 2; + } + if(_plat__ACT_GetSignaled(act)) + go.signaledACT |= (1 << act); +} +/* 7.8.3.4 ActGetSignaled() */ +/* This function returns the state of the signaled flag associated with an ACT. */ +BOOL +ActGetSignaled( + TPM_RH actHandle + ) +{ + UINT32 act = actHandle - TPM_RH_ACT_0; + // + return _plat__ACT_GetSignaled(act); +} +#endif // libtpms added +/* 7.8.3.5 ActShutdown() */ +/* This function saves the current state of the counters */ +BOOL +ActShutdown( + TPM_SU state //IN: the type of the shutdown. + ) +{ + // if this is not shutdown state, then the only type of startup is TPM_RESTART + // so the timer values will be cleared. If this is shutdown state, get the current + // countdown and signaled values. Plus, if the counter has not been updated + // since the last restart, divide the time by 2 so that there is no attack on the + // countdown by saving the countdown state early and then not using the TPM. + if(state == TPM_SU_STATE) + { + // This will be populated as each of the ACT is queried +#ifndef __ACT_DISABLED // libtpms added + go.signaledACT = 0; +#endif // libtpms added + // Get the current count and the signaled state +#define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(SAVE_ACT_STATE); + } + return TRUE; +} +/* 7.8.3.6 ActIsImplemented() */ +/* This function determines if an ACT is implemented in both the TPM and the platform code. */ +BOOL +ActIsImplemented( + UINT32 act + ) +{ +#define CASE_ACT_ + // This switch accounts for the TPM implemented values. + switch(act) + { +#ifndef __ACT_DISABLED // libtpms added + FOR_EACH_ACT(CASE_ACT_NUMBER) + // This ensures that the platorm implemented the values implemented by + // the TPM + return _plat__ACT_GetImplemented(act); +#endif // libtpms added + default: + break; + } + return FALSE; +} +/* 7.8.3.7 ActCounterUpdate() */ +/* This function updates the ACT counter. If the counter already has a pending update, it returns + TPM_RC_RETRY so that the update can be tried again later. */ +#if CC_ACT_SetTimeout // libtpms added +TPM_RC +ActCounterUpdate( + TPM_RH handle, //IN: the handle of the act + UINT32 newValue //IN: the value to set in the ACT + ) +{ + UINT32 act; + TPM_RC result; + // + act = handle - TPM_RH_ACT_0; + // This should never fail, but... + if(!_plat__ACT_GetImplemented(act)) + result = TPM_RC_VALUE; + else + { + // Will need to clear orderly so fail if we are orderly and NV is not available + if(NV_IS_ORDERLY) + RETURN_IF_NV_IS_NOT_AVAILABLE; + // if the attempt to update the counter fails, it means that there is an + // update pending so wait until it has occurred and then do an update. + if(!_plat__ACT_UpdateCounter(act, newValue)) + result = TPM_RC_RETRY; + else + { + // Indicate that the ACT has been updated since last TPM2_Startup(). + s_ActUpdated |= (UINT16)(1 << act); + + // Clear the preservedSignaled attribute. + go.preservedSignaled &= ~((UINT16)(1 << act)); + + // Need to clear the orderly flag + g_clearOrderly = TRUE; + + result = TPM_RC_SUCCESS; + } + } + return result; +} +#endif // libtpms added +/* 7.8.3.8 ActGetCapabilityData() */ +/* This function returns the list of ACT data */ +/* Return Value Meaning */ +/* YES if more ACT data is available */ +/* NO if no more ACT data to */ +TPMI_YES_NO +ActGetCapabilityData( + TPM_HANDLE actHandle, // IN: the handle for the starting ACT + UINT32 maxCount, // IN: maximum allowed return values + TPML_ACT_DATA *actList // OUT: ACT data list + ) +{ + // Initialize output property list + actList->count = 0; + + // Make sure that the starting handle value is in range (again) + if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F)) + return FALSE; + // The maximum count of curves we may return is MAX_ECC_CURVES + if(maxCount > MAX_ACT_DATA) + maxCount = MAX_ACT_DATA; + // Scan the ACT data from the starting ACT + for(; actHandle <= TPM_RH_ACT_F; actHandle++) + { + UINT32 act = actHandle - TPM_RH_ACT_0; + if(actList->count < maxCount) + { + if(ActIsImplemented(act)) + { + TPMS_ACT_DATA *actData = &actList->actData[actList->count]; + // + memset(&actData->attributes, 0, sizeof(actData->attributes)); + actData->handle = actHandle; + actData->timeout = _plat__ACT_GetRemaining(act); + if (_plat__ACT_GetSignaled(act)) + SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + else + CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + actList->count++; + } + } + else + { + if(_plat__ACT_GetImplemented(act)) + return YES; + } + } + // If we get here, either all of the ACT values were put in the list, or the list + // was filled and there are no more ACT values to return + return NO; +} |