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
TPM2_NV_Extend(NV_Extend_In * in)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