blob: 197bb1af6dbbb0a311bbb1ab3d1b7e64bb54243a [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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//
21TPM_RC
22TPM2_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}