Line | Count | Source (jump to first uncovered line) |
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 "Attest_spt_fp.h" |
10 | | #include "NV_spt_fp.h" |
11 | | #include "NV_Certify_fp.h" |
12 | | // |
13 | | // |
14 | | // Error Returns Meaning |
15 | | // |
16 | | // TPM_RC_NV_AUTHORIZATION the authorization was valid but the authorizing entity (authHandle) is |
17 | | // not allowed to read from the Index referenced by nvIndex |
18 | | // TPM_RC_KEY signHandle does not reference a signing key |
19 | | // TPM_RC_NV_LOCKED Index referenced by nvIndex is locked for reading |
20 | | // TPM_RC_NV_RANGE offset plus size extends outside of the data range of the Index |
21 | | // referenced by nvIndex |
22 | | // TPM_RC_NV_UNINITIALIZED Index referenced by nvIndex has not been written |
23 | | // TPM_RC_SCHEME inScheme is not an allowed value for the key definition |
24 | | // |
25 | | TPM_RC |
26 | | TPM2_NV_Certify( |
27 | | NV_Certify_In *in, // IN: input parameter list |
28 | | NV_Certify_Out *out // OUT: output parameter list |
29 | | ) |
30 | 0 | { |
31 | 0 | TPM_RC result; |
32 | 0 | NV_INDEX nvIndex; |
33 | 0 | TPMS_ATTEST certifyInfo; |
34 | | |
35 | | // Attestation command may cause the orderlyState to be cleared due to |
36 | | // the reporting of clock info. If this is the case, check if NV is |
37 | | // available first |
38 | 0 | if(gp.orderlyState != SHUTDOWN_NONE) |
39 | 0 | { |
40 | | // The command needs NV update. Check if NV is available. |
41 | | // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at |
42 | | // this point |
43 | 0 | result = NvIsAvailable(); |
44 | 0 | if(result != TPM_RC_SUCCESS) |
45 | 0 | return result; |
46 | 0 | } |
47 | | |
48 | | // Input Validation |
49 | | |
50 | | // Get NV index info |
51 | 0 | NvGetIndexInfo(in->nvIndex, &nvIndex); |
52 | | |
53 | | // Common access checks. A TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED |
54 | | // error may be returned at this point |
55 | 0 | result = NvReadAccessChecks(in->authHandle, in->nvIndex); |
56 | 0 | if(result != TPM_RC_SUCCESS) |
57 | 0 | return result; |
58 | | |
59 | | // make sure that the selection is within the range of the Index (cast to avoid |
60 | | // any wrap issues with addition) |
61 | 0 | if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex.publicArea.dataSize) |
62 | 0 | return TPM_RC_NV_RANGE; |
63 | | |
64 | | // Make sure the data will fit the return buffer. |
65 | | // NOTE: This check may be modified if the output buffer will not hold the |
66 | | // maximum sized NV buffer as part of the certified data. The difference in |
67 | | // size could be substantial if the signature scheme was produced a large |
68 | | // signature (e.g., RSA 4096). |
69 | 0 | if(in->size > MAX_NV_BUFFER_SIZE) |
70 | 0 | return TPM_RC_VALUE + RC_NV_Certify_size; |
71 | | |
72 | | |
73 | | // Command Output |
74 | | |
75 | | // Filling in attest information |
76 | | // Common fields |
77 | | // FillInAttestInfo can return TPM_RC_SCHEME or TPM_RC_KEY |
78 | 0 | result = FillInAttestInfo(in->signHandle, |
79 | 0 | &in->inScheme, |
80 | 0 | &in->qualifyingData, |
81 | 0 | &certifyInfo); |
82 | 0 | if(result != TPM_RC_SUCCESS) |
83 | 0 | { |
84 | 0 | if(result == TPM_RC_KEY) |
85 | 0 | return TPM_RC_KEY + RC_NV_Certify_signHandle; |
86 | 0 | else |
87 | 0 | return RcSafeAddToResult(result, RC_NV_Certify_inScheme); |
88 | 0 | } |
89 | | // NV certify specific fields |
90 | | // Attestation type |
91 | 0 | certifyInfo.type = TPM_ST_ATTEST_NV; |
92 | | |
93 | | // Get the name of the index |
94 | 0 | certifyInfo.attested.nv.indexName.t.size = |
95 | 0 | NvGetName(in->nvIndex, &certifyInfo.attested.nv.indexName.t.name); |
96 | | |
97 | | // Set the return size |
98 | 0 | certifyInfo.attested.nv.nvContents.t.size = in->size; |
99 | | |
100 | | // Set the offset |
101 | 0 | certifyInfo.attested.nv.offset = in->offset; |
102 | | |
103 | | // Perform the read |
104 | 0 | NvGetIndexData(in->nvIndex, &nvIndex, |
105 | 0 | in->offset, in->size, |
106 | 0 | certifyInfo.attested.nv.nvContents.t.buffer); |
107 | | |
108 | | // Sign attestation structure. A NULL signature will be returned if |
109 | | // signHandle is TPM_RH_NULL. SignAttestInfo() may return TPM_RC_VALUE, |
110 | | // TPM_RC_SCHEME or TPM_RC_ATTRUBUTES. |
111 | | // Note: SignAttestInfo may return TPM_RC_ATTRIBUTES if the key is not a |
112 | | // signing key but that was checked above. TPM_RC_VALUE would mean that the |
113 | | // data to sign is too large but the data to sign is a digest |
114 | 0 | result = SignAttestInfo(in->signHandle, |
115 | 0 | &in->inScheme, |
116 | 0 | &certifyInfo, |
117 | 0 | &in->qualifyingData, |
118 | 0 | &out->certifyInfo, |
119 | 0 | &out->signature); |
120 | 0 | if(result != TPM_RC_SUCCESS) |
121 | 0 | return result; |
122 | | |
123 | | // orderly state should be cleared because of the reporting of clock info |
124 | | // if signing happens |
125 | 0 | if(in->signHandle != TPM_RH_NULL) |
126 | 0 | g_clearOrderly = TRUE; |
127 | |
|
128 | 0 | return TPM_RC_SUCCESS; |
129 | 0 | } |