/
githubmirror
/
libtpms
Обзор
Документация
Войти
/
githubmirror
/
libtpms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/tpm2/NVCommands.c
632 строки
25 KB
Stefan Berger
Sync: Introduce platform functions for accessing NV indices
13 фев 2026, 17:59
13 фев 2026, 17:59
ea44b01
Код
Авторство
О чём код?
/********************************************************************************/ /* */ /* Non-Volatile Storage */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* */ /* 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 - 2024 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "NV_DefineSpace_fp.h" #if CC_NV_DefineSpace // Conditional expansion of this file /*(See part 3 specification) // Define a NV index space */ // Return Type: TPM_RC // TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM // phEnable_NV is clear preventing access to NV // data in the platform hierarchy. // TPM_RC_ATTRIBUTES attributes of the index are not consistent // TPM_RC_NV_DEFINED index already exists // TPM_RC_NV_SPACE insufficient space for the index // TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is // larger than the digest size of // 'publicInfo->nameAlg'; or 'publicInfo->dataSize' // is not consistent with 'publicInfo->attributes' // (this includes the case when the index is // larger than a MAX_NV_BUFFER_SIZE but the // TPMA_NV_WRITEALL attribute is SET) TPM_RC TPM2_NV_DefineSpace( NV_DefineSpace_In *in // IN: input parameter list ) { // This command only supports TPM_HT_NV_INDEX-typed NV indices. if(HandleGetType(in->publicInfo.nvPublic.nvIndex) != TPM_HT_NV_INDEX) { return TPM_RCS_HANDLE + RC_NV_DefineSpace_publicInfo; } return NvDefineSpace(in->authHandle, &in->auth, &in->publicInfo.nvPublic, RC_NV_DefineSpace_authHandle, RC_NV_DefineSpace_auth, RC_NV_DefineSpace_publicInfo); } #endif // CC_NV_DefineSpace #include "Tpm.h" #include "NV_UndefineSpace_fp.h" #if CC_NV_UndefineSpace // Conditional expansion of this file TPM_RC TPM2_NV_UndefineSpace( NV_UndefineSpace_In *in // IN: input parameter list ) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex; // The owner may only delete an index that was defined with ownerAuth. The // platform may delete an index that was created with either authorization. if(in->authHandle == TPM_RH_OWNER && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) return TPM_RC_NV_AUTHORIZATION; // Internal Data Update // Call implementation dependent internal routine to delete NV index return NvDeleteIndex(nvIndex, locator); } #endif // CC_NV_UndefineSpace #include "Tpm.h" #include "NV_UndefineSpaceSpecial_fp.h" #include "SessionProcess_fp.h" #if CC_NV_UndefineSpaceSpecial // Conditional expansion of this file TPM_RC TPM2_NV_UndefineSpaceSpecial( NV_UndefineSpaceSpecial_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex; // Internal Data Update // Call implementation dependent internal routine to delete NV index result = NvDeleteIndex(nvIndex, locator); // If we just removed the index providing the authorization, make sure that the // authorization session computation is modified so that it doesn't try to // access the authValue of the just deleted index if(result == TPM_RC_SUCCESS) SessionRemoveAssociationToHandle(in->nvIndex); return result; } #endif // CC_NV_UndefineSpaceSpecial #include "Tpm.h" #include "NV_Write_fp.h" #if CC_NV_Write // Conditional expansion of this file TPM_RC TPM2_NV_Write( NV_Write_In *in // IN: input parameter list ) { NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL); TPMA_NV attributes = nvIndex->publicArea.attributes; TPM_RC result; // Input Validation // Common Read-Only mode check. May return TPM_RC_READ_ONLY result = NvReadOnlyModeChecks(attributes); if(result != TPM_RC_SUCCESS) return result; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, attributes); if(result != TPM_RC_SUCCESS) return result; // Bits index, extend index or counter index may not be updated by // TPM2_NV_Write if(IsNvCounterIndex(attributes) || IsNvBitsIndex(attributes) || IsNvExtendIndex(attributes)) return TPM_RC_ATTRIBUTES; // Make sure that the offset is not too large if(in->offset > nvIndex->publicArea.dataSize) return TPM_RCS_VALUE + RC_NV_Write_offset; // Make sure that the selection is within the range of the Index if(in->data.t.size > (nvIndex->publicArea.dataSize - in->offset)) return TPM_RC_NV_RANGE; // If this index requires a full sized write, make sure that input range is // full sized. // Note: if the requested size is the same as the Index data size, then offset // will have to be zero. Otherwise, the range check above would have failed. if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL) && in->data.t.size < nvIndex->publicArea.dataSize) return TPM_RC_NV_RANGE; // Internal Data Update // Perform the write. This called routine will SET the TPMA_NV_WRITTEN // attribute if it has not already been SET. If NV isn't available, an error // will be returned. return NvWriteIndexData(nvIndex, in->offset, in->data.t.size, in->data.t.buffer); } #endif // CC_NV_Write #include "Tpm.h" #include "NV_Increment_fp.h" #if CC_NV_Increment // Conditional expansion of this file TPM_RC TPM2_NV_Increment( NV_Increment_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); UINT64 countValue; // Input Validation // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is a counter if(!IsNvCounterIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex; // Internal Data Update // If counter index is not been written, initialize it if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) countValue = NvReadMaxCount(); else // Read NV data in native format for TPM CPU. countValue = NvGetUINT64Data(nvIndex, locator); // Do the increment countValue++; // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may // be returned at this point. If necessary, this function will set the // TPMA_NV_WRITTEN attribute result = NvWriteUINT64Data(nvIndex, countValue); if(result == TPM_RC_SUCCESS) { // If a counter just rolled over, then force the NV update. // Note, if this is an orderly counter, then the write-back needs to be // forced, for other counters, the write-back will happen anyway if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY) && (countValue & MAX_ORDERLY_COUNT) == 0 ) { // Need to force an NV update of orderly data SET_NV_UPDATE(UT_ORDERLY); } } return result; } #endif // CC_NV_Increment #include "Tpm.h" #include "NV_Extend_fp.h" #if CC_NV_Extend // Conditional expansion of this file TPM_RC TPM2_NV_Extend( NV_Extend_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPM2B_DIGEST oldDigest; TPM2B_DIGEST newDigest; HASH_STATE hashState; // Input Validation // Common Read-Only mode check. May return TPM_RC_READ_ONLY result = NvReadOnlyModeChecks(nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is an extend index if(!IsNvExtendIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_Extend_nvIndex; // Internal Data Update // Perform the write. oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg); pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer)); if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) { NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer); } else { MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size); } // Start hash newDigest.t.size = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); // Adding old digest CryptDigestUpdate2B(&hashState, &oldDigest.b); // Adding new data CryptDigestUpdate2B(&hashState, &in->data.b); // Complete hash CryptHashEnd2B(&hashState, &newDigest.b); // Write extended hash back. // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary return NvWriteIndexData(nvIndex, 0, newDigest.t.size, newDigest.t.buffer); } #endif // CC_NV_Extend #include "Tpm.h" #include "NV_SetBits_fp.h" #if CC_NV_SetBits // Conditional expansion of this file TPM_RC TPM2_NV_SetBits( NV_SetBits_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); UINT64 oldValue; UINT64 newValue; // Input Validation // Common Read-Only mode check. May return TPM_RC_READ_ONLY result = NvReadOnlyModeChecks(nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is a bit field if(!IsNvBitsIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex; // If index is not been written, initialize it if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) oldValue = 0; else // Read index data oldValue = NvGetUINT64Data(nvIndex, locator); // Figure out what the new value is going to be newValue = oldValue | in->bits; // Internal Data Update return NvWriteUINT64Data(nvIndex, newValue); } #endif // CC_NV_SetBits #include "Tpm.h" #include "NV_WriteLock_fp.h" #if CC_NV_WriteLock // Conditional expansion of this file TPM_RC TPM2_NV_WriteLock( NV_WriteLock_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMA_NV nvAttributes = nvIndex->publicArea.attributes; // Input Validation: // Common Read-Only mode check. May return TPM_RC_READ_ONLY result = NvReadOnlyModeChecks(nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvAttributes); if(result != TPM_RC_SUCCESS) { if(result == TPM_RC_NV_AUTHORIZATION) return result; // If write access failed because the index is already locked, then it is // no error. return TPM_RC_SUCCESS; } // if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index // can not be write-locked if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE) && !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR)) return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex; // Internal Data Update // Set the WRITELOCK attribute. // Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check // above would have failed and this code isn't executed. SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED); // Write index info back return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); } #endif // CC_NV_WriteLock #include "Tpm.h" #include "NV_GlobalWriteLock_fp.h" #if CC_NV_GlobalWriteLock // Conditional expansion of this file TPM_RC TPM2_NV_GlobalWriteLock( NV_GlobalWriteLock_In *in // IN: input parameter list ) { // Input parameter (the authorization handle) is not reference in command action. NOT_REFERENCED(in); // Internal Data Update // Implementation dependent method of setting the global lock return NvSetGlobalLock(); } #endif // CC_NV_GlobalWriteLock #include "Tpm.h" #include "NV_ReadLock_fp.h" #if CC_NV_ReadLock // Conditional expansion of this file TPM_RC TPM2_NV_ReadLock( NV_ReadLock_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; // The referenced index has been checked multiple times before this is called // so it must be present and will be loaded into cache NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMA_NV nvAttributes = nvIndex->publicArea.attributes; // Input Validation // Common Read-Only mode check. May return TPM_RC_READ_ONLY result = NvReadOnlyModeChecks(nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Common read access checks. NvReadAccessChecks() may return // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvAttributes); if(result == TPM_RC_NV_AUTHORIZATION) return TPM_RC_NV_AUTHORIZATION; // Index is already locked for write else if(result == TPM_RC_NV_LOCKED) return TPM_RC_SUCCESS; // If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue. // It is not an error to read lock an uninitialized Index. // if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR)) return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex; // Internal Data Update // Set the READLOCK attribute SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED); // Write NV info back return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); } #endif // CC_NV_ReadLock #include "Tpm.h" #include "NV_ChangeAuth_fp.h" #if CC_NV_ChangeAuth // Conditional expansion of this file TPM_RC TPM2_NV_ChangeAuth( NV_ChangeAuth_In *in // IN: input parameter list ) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // Remove trailing zeros and make sure that the result is not larger than the // digest of the nameAlg. if(MemoryRemoveTrailingZeros(&in->newAuth) > CryptHashGetDigestSize(nvIndex->publicArea.nameAlg)) return TPM_RCS_SIZE + RC_NV_ChangeAuth_newAuth; // Internal Data Update // Change authValue return NvWriteIndexAuth(locator, &in->newAuth); } #endif // CC_NV_ChangeAuth #include "Tpm.h" #include "Attest_spt_fp.h" #include "NV_Certify_fp.h" #if CC_NV_Certify // Conditional expansion of this file TPM_RC TPM2_NV_Certify( NV_Certify_In *in, // IN: input parameter list NV_Certify_Out *out // OUT: output parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMS_ATTEST certifyInfo; OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_NV_Certify_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_NV_Certify_inScheme; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // make sure that the selection is within the range of the Index (cast to avoid // any wrap issues with addition) if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize) return TPM_RC_NV_RANGE; // Make sure the data will fit the return buffer // NOTE: This check may be modified if the output buffer will not hold the // maximum sized NV buffer as part of the certified data. The difference in // size could be substantial if the signature scheme was produced a large // signature (e.g., RSA 4096). if(in->size > MAX_NV_BUFFER_SIZE) return TPM_RCS_VALUE + RC_NV_Certify_size; // Command Output // Fill in attest information common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); // Get the name of the index NvGetIndexName(nvIndex, &certifyInfo.attested.nv.indexName); // See if this is old format or new format if ((in->size != 0) || (in->offset != 0)) { // NV certify specific fields // Attestation type certifyInfo.type = TPM_ST_ATTEST_NV; // Set the return size certifyInfo.attested.nv.nvContents.t.size = in->size; // Set the offset certifyInfo.attested.nv.offset = in->offset; // Perform the read NvGetIndexData(nvIndex, locator, in->offset, in->size, certifyInfo.attested.nv.nvContents.t.buffer); } else { HASH_STATE hashState; // This is to sign a digest of the data certifyInfo.type = TPM_ST_ATTEST_NV_DIGEST; // Initialize the hash before calling the function to add the Index data to // the hash. certifyInfo.attested.nvDigest.nvDigest.t.size = CryptHashStart(&hashState, in->inScheme.details.any.hashAlg); NvHashIndexData(&hashState, nvIndex, locator, 0, nvIndex->publicArea.dataSize); CryptHashEnd2B(&hashState, &certifyInfo.attested.nvDigest.nvDigest.b); } // Sign attestation structure. A NULL signature will be returned if // signObject is NULL. return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, &in->qualifyingData, &out->certifyInfo, &out->signature); } #endif // CC_NV_Certify #include "Tpm.h" #include "NV_DefineSpace2_fp.h" #if CC_NV_DefineSpace2 // Conditional expansion of this file /*(See part 3 specification) // Define a NV index space */ // Return Type: TPM_RC // TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM // phEnable_NV is clear preventing access to NV // data in the platform hierarchy. // TPM_RC_ATTRIBUTES attributes of the index are not consistent // TPM_RC_NV_DEFINED index already exists // TPM_RC_NV_SPACE insufficient space for the index // TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is // larger than the digest size of // 'publicInfo->nameAlg'; or 'publicInfo->dataSize' // is not consistent with 'publicInfo->attributes' // (this includes the case when the index is // larger than a MAX_NV_BUFFER_SIZE but the // TPMA_NV_WRITEALL attribute is SET) TPM_RC TPM2_NV_DefineSpace2(NV_DefineSpace2_In* in // IN: input parameter list ) { TPM_RC result; TPMS_NV_PUBLIC legacyPublic; // Input Validation // Validate the handle type and the (handle-type-specific) attributes. switch(in->publicInfo.nvPublic2.handleType) { case TPM_HT_NV_INDEX: break; # if EXTERNAL_NV case TPM_HT_EXTERNAL_NV: // The reference implementation may let you define an "external" NV // index, but it doesn't currently support setting any of the extended // bits for customizing the behavior of external NV. if((TPMA_NV_EXP_TO_UINT64( in->publicInfo.nvPublic2.nvPublic2.externalNV.attributes) & 0xffffffff00000000) != 0) { return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace2_publicInfo; } break; # endif default: return TPM_RCS_HANDLE + RC_NV_DefineSpace2_publicInfo; } result = NvPublicFromNvPublic2(&in->publicInfo.nvPublic2, &legacyPublic); if(result != TPM_RC_SUCCESS) { return RcSafeAddToResult(result, RC_NV_DefineSpace2_publicInfo); } return NvDefineSpace(in->authHandle, &in->auth, &legacyPublic, RC_NV_DefineSpace2_authHandle, RC_NV_DefineSpace2_auth, RC_NV_DefineSpace2_publicInfo); } #endif // CC_NV_DefineSpace