blob: 85c42a6925ea7e3ef0b48622a79110849f805b09 [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 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//
25TPM_RC
26FillInAttestInfo(
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 // For null sign handle, the QN is TPM_RH_NULL
Vadim Bendeburyb86371b2015-05-27 18:16:19 -070044 buffer = attest->qualifiedSigner.t.buffer;
Vadim Bendebury56797522015-05-20 10:32:25 -070045 attest->qualifiedSigner.t.size =
46 TPM_HANDLE_Marshal(&signHandle, &buffer, NULL);
47 }
48 else
49 {
50 // Certifying object qualified name
51 // if the scheme is anonymous, this is an empty buffer
52 if(CryptIsSchemeAnonymous(scheme->scheme))
53 attest->qualifiedSigner.t.size = 0;
54 else
55 ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner);
56 }
57 // current clock in plain text
58 TimeFillInfo(&attest->clockInfo);
59 // Firmware version in plain text
60 attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8));
61 attest->firmwareVersion += gp.firmwareV2;
62 // Get the hierarchy of sign object. For NULL sign handle, the hierarchy
63 // will be TPM_RH_NULL
64 signHierarhcy = EntityGetHierarchy(signHandle);
65 if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT)
66 {
67 // For sign object is not in platform or endorsement hierarchy,
68 // obfuscate the clock and firmwereVersion information
69 UINT64 obfuscation[2];
70 TPMI_ALG_HASH hashAlg;
71 // Get hash algorithm
72 if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER)
73 {
74 hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
75 }
76 else
77 {
78 OBJECT *signObject = NULL;
79 signObject = ObjectGet(signHandle);
80 hashAlg = signObject->publicArea.nameAlg;
81 }
82 KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE",
83 &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL);
84 // Obfuscate data
85 attest->firmwareVersion += obfuscation[0];
86 attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
87 attest->clockInfo.restartCount += (UINT32)obfuscation[1];
88 }
89 // External data
90 if(CryptIsSchemeAnonymous(scheme->scheme))
91 attest->extraData.t.size = 0;
92 else
93 {
94 // If we move the data to the attestation structure, then we will not use
95 // it in the signing operation except as part of the signed data
96 attest->extraData = *data;
97 data->t.size = 0;
98 }
99 return TPM_RC_SUCCESS;
100}
101//
102//
103// SignAttestInfo()
104//
105// Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned.
106//
107//
108//
109//
110// Error Returns Meaning
111//
112// TPM_RC_ATTRIBUTES signHandle references not a signing key
113// TPM_RC_SCHEME scheme is not compatible with signHandle type
114// TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of
115// signHandle (for an RSA key); invalid commit status or failed to
116// generate r value (for an ECC key)
117//
118TPM_RC
119SignAttestInfo(
120 TPMI_DH_OBJECT signHandle, // IN: handle of sign object
121 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
122 TPMS_ATTEST *certifyInfo, // IN: the data to be signed
123 TPM2B_DATA *qualifyingData, // IN: extra data for the signing proce
124 TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be
125 // signed
126 TPMT_SIGNATURE *signature // OUT: signature
127 )
128{
129 TPM_RC result;
130 TPMI_ALG_HASH hashAlg;
131 BYTE *buffer;
132 HASH_STATE hashState;
133 TPM2B_DIGEST digest;
134 // Marshal TPMS_ATTEST structure for hash
Vadim Bendeburyb86371b2015-05-27 18:16:19 -0700135 buffer = attest->t.buffer;
Vadim Bendebury56797522015-05-20 10:32:25 -0700136 attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL);
137 if(signHandle == TPM_RH_NULL)
138 {
139 signature->sigAlg = TPM_ALG_NULL;
140 }
141 else
142 {
143 // Attestation command may cause the orderlyState to be cleared due to
144 // the reporting of clock info. If this is the case, check if NV is
145 // available first
146 if(gp.orderlyState != SHUTDOWN_NONE)
147 {
148 // The command needs NV update. Check if NV is available.
149 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
150 // this point
151 result = NvIsAvailable();
152 if(result != TPM_RC_SUCCESS)
153 return result;
154 }
155 // Compute hash
156 hashAlg = scheme->details.any.hashAlg;
157 digest.t.size = CryptStartHash(hashAlg, &hashState);
Vadim Bendeburyb86371b2015-05-27 18:16:19 -0700158 CryptUpdateDigest(&hashState, attest->t.size, attest->t.buffer);
Vadim Bendebury56797522015-05-20 10:32:25 -0700159 CryptCompleteHash2B(&hashState, &digest.b);
160 // If there is qualifying data, need to rehash the the data
161 // hash(qualifyingData || hash(attestationData))
162 if(qualifyingData->t.size != 0)
163 {
164 CryptStartHash(hashAlg, &hashState);
165 CryptUpdateDigest(&hashState,
166 qualifyingData->t.size,
167 qualifyingData->t.buffer);
168 CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer);
169 CryptCompleteHash2B(&hashState, &digest.b);
170 }
171 // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
172 // TPM_RC_ATTRIBUTES error may be returned at this point
173 return CryptSign(signHandle,
174 scheme,
175 &digest,
176 signature);
177 }
178 return TPM_RC_SUCCESS;
179}