1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 3: Commands 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include "InternalRoutines.h" 9 #include "NV_Extend_fp.h" 10 #include "NV_spt_fp.h" 11 // 12 // 13 // Error Returns Meaning 14 // 15 // TPM_RC_ATTRIBUTES the TPMA_NV_EXTEND attribute is not SET in the Index referenced 16 // by nvIndex 17 // TPM_RC_NV_AUTHORIZATION the authorization was valid but the authorizing entity (authHandle) is 18 // not allowed to write to the Index referenced by nvIndex 19 // TPM_RC_NV_LOCKED the Index referenced by nvIndex is locked for writing 20 // 21 TPM_RC 22 TPM2_NV_Extend( 23 NV_Extend_In *in // IN: input parameter list 24 ) 25 { 26 TPM_RC result; 27 NV_INDEX nvIndex; 28 29 TPM2B_DIGEST oldDigest; 30 TPM2B_DIGEST newDigest; 31 HASH_STATE hashState; 32 33 // Input Validation 34 35 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION 36 // or TPM_RC_NV_LOCKED 37 result = NvWriteAccessChecks(in->authHandle, in->nvIndex); 38 if(result != TPM_RC_SUCCESS) 39 return result; 40 41 // Get NV index info 42 NvGetIndexInfo(in->nvIndex, &nvIndex); 43 44 // Make sure that this is an extend index 45 if(nvIndex.publicArea.attributes.TPMA_NV_EXTEND != SET) 46 return TPM_RC_ATTRIBUTES + RC_NV_Extend_nvIndex; 47 48 // If the Index is not-orderly, or if this is the first write, NV will 49 // need to be updated. 50 if( nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR 51 || nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR) 52 { 53 // Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE 54 // TPM_RC_NV_RATE or TPM_RC_SUCCESS. 55 result = NvIsAvailable(); 56 if(result != TPM_RC_SUCCESS) 57 return result; 58 } 59 60 // Internal Data Update 61 62 // Perform the write. 63 oldDigest.t.size = CryptGetHashDigestSize(nvIndex.publicArea.nameAlg); 64 pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer)); 65 if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 66 { 67 NvGetIndexData(in->nvIndex, &nvIndex, 0, 68 oldDigest.t.size, oldDigest.t.buffer); 69 } 70 else 71 { 72 MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size); 73 } 74 // Start hash 75 newDigest.t.size = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState); 76 77 // Adding old digest 78 CryptUpdateDigest2B(&hashState, &oldDigest.b); 79 80 // Adding new data 81 CryptUpdateDigest2B(&hashState, &in->data.b); 82 83 // Complete hash 84 CryptCompleteHash2B(&hashState, &newDigest.b); 85 86 // Write extended hash back. 87 // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary 88 return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 89 newDigest.t.size, newDigest.t.buffer); 90 } 91