1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
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 //
11 //
12 // Functions
13 //
14 // FillInAttestInfo()
15 //
16 // Fill in common fields of TPMS_ATTEST structure.
17 //
18 // Error Returns Meaning
19 //
20 // TPM_RC_KEY key referenced by signHandle is not a signing key
21 // TPM_RC_SCHEME both scheme and key's default scheme are empty; or scheme is
22 // empty while key's default scheme requires explicit input scheme (split
23 // signing); or non-empty default key scheme differs from scheme
24 //
25 TPM_RC
FillInAttestInfo(TPMI_DH_OBJECT signHandle,TPMT_SIG_SCHEME * scheme,TPM2B_DATA * data,TPMS_ATTEST * attest)26 FillInAttestInfo(
27 TPMI_DH_OBJECT signHandle, // IN: handle of signing object
28 TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing
29 TPM2B_DATA *data, // IN: qualifying data
30 TPMS_ATTEST *attest // OUT: attest structure
31 )
32 {
33 TPM_RC result;
34 TPMI_RH_HIERARCHY signHierarhcy;
35 result = CryptSelectSignScheme(signHandle, scheme);
36 if(result != TPM_RC_SUCCESS)
37 return result;
38 // Magic number
39 attest->magic = TPM_GENERATED_VALUE;
40 if(signHandle == TPM_RH_NULL)
41 {
42 BYTE *buffer;
43 INT32 bufferSize;
44 // For null sign handle, the QN is TPM_RH_NULL
45 buffer = attest->qualifiedSigner.t.name;
46 bufferSize = sizeof(TPM_HANDLE);
47 attest->qualifiedSigner.t.size =
48 TPM_HANDLE_Marshal(&signHandle, &buffer, &bufferSize);
49 }
50 else
51 {
52 // Certifying object qualified name
53 // if the scheme is anonymous, this is an empty buffer
54 if(CryptIsSchemeAnonymous(scheme->scheme))
55 attest->qualifiedSigner.t.size = 0;
56 else
57 ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner);
58 }
59 // current clock in plain text
60 TimeFillInfo(&attest->clockInfo);
61 // Firmware version in plain text
62 attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8));
63 attest->firmwareVersion += gp.firmwareV2;
64 // Get the hierarchy of sign object. For NULL sign handle, the hierarchy
65 // will be TPM_RH_NULL
66 signHierarhcy = EntityGetHierarchy(signHandle);
67 if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT)
68 {
69 // For sign object is not in platform or endorsement hierarchy,
70 // obfuscate the clock and firmwereVersion information
71 UINT64 obfuscation[2];
72 TPMI_ALG_HASH hashAlg;
73 // Get hash algorithm
74 if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER)
75 {
76 hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
77 }
78 else
79 {
80 OBJECT *signObject = NULL;
81 signObject = ObjectGet(signHandle);
82 hashAlg = signObject->publicArea.nameAlg;
83 }
84 KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE",
85 &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL);
86 // Obfuscate data
87 attest->firmwareVersion += obfuscation[0];
88 attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
89 attest->clockInfo.restartCount += (UINT32)obfuscation[1];
90 }
91 // External data
92 if(CryptIsSchemeAnonymous(scheme->scheme))
93 attest->extraData.t.size = 0;
94 else
95 {
96 // If we move the data to the attestation structure, then we will not use
97 // it in the signing operation except as part of the signed data
98 attest->extraData = *data;
99 data->t.size = 0;
100 }
101 return TPM_RC_SUCCESS;
102 }
103 //
104 //
105 // SignAttestInfo()
106 //
107 // Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned.
108 //
109 //
110 //
111 //
112 // Error Returns Meaning
113 //
114 // TPM_RC_ATTRIBUTES signHandle references not a signing key
115 // TPM_RC_SCHEME scheme is not compatible with signHandle type
116 // TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of
117 // signHandle (for an RSA key); invalid commit status or failed to
118 // generate r value (for an ECC key)
119 //
120 TPM_RC
SignAttestInfo(TPMI_DH_OBJECT signHandle,TPMT_SIG_SCHEME * scheme,TPMS_ATTEST * certifyInfo,TPM2B_DATA * qualifyingData,TPM2B_ATTEST * attest,TPMT_SIGNATURE * signature)121 SignAttestInfo(
122 TPMI_DH_OBJECT signHandle, // IN: handle of sign object
123 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
124 TPMS_ATTEST *certifyInfo, // IN: the data to be signed
125 TPM2B_DATA *qualifyingData, // IN: extra data for the signing proce
126 TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be
127 // signed
128 TPMT_SIGNATURE *signature // OUT: signature
129 )
130 {
131 TPM_RC result;
132 TPMI_ALG_HASH hashAlg;
133 BYTE *buffer;
134 INT32 bufferSize;
135 HASH_STATE hashState;
136 TPM2B_DIGEST digest;
137 // Marshal TPMS_ATTEST structure for hash
138 buffer = attest->t.attestationData;
139 bufferSize = sizeof(TPMS_ATTEST);
140 attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, &bufferSize);
141 if(signHandle == TPM_RH_NULL)
142 {
143 signature->sigAlg = TPM_ALG_NULL;
144 }
145 else
146 {
147 // Attestation command may cause the orderlyState to be cleared due to
148 // the reporting of clock info. If this is the case, check if NV is
149 // available first
150 if(gp.orderlyState != SHUTDOWN_NONE)
151 {
152 // The command needs NV update. Check if NV is available.
153 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
154 // this point
155 result = NvIsAvailable();
156 if(result != TPM_RC_SUCCESS)
157 return result;
158 }
159 // Compute hash
160 hashAlg = scheme->details.any.hashAlg;
161 digest.t.size = CryptStartHash(hashAlg, &hashState);
162 CryptUpdateDigest(&hashState, attest->t.size, attest->t.attestationData);
163 CryptCompleteHash2B(&hashState, &digest.b);
164 // If there is qualifying data, need to rehash the the data
165 // hash(qualifyingData || hash(attestationData))
166 if(qualifyingData->t.size != 0)
167 {
168 CryptStartHash(hashAlg, &hashState);
169 CryptUpdateDigest(&hashState,
170 qualifyingData->t.size,
171 qualifyingData->t.buffer);
172 CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer);
173 CryptCompleteHash2B(&hashState, &digest.b);
174 }
175 // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
176 // TPM_RC_ATTRIBUTES error may be returned at this point
177 return CryptSign(signHandle,
178 scheme,
179 &digest,
180 signature);
181 }
182 return TPM_RC_SUCCESS;
183 }
184