1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 //** Includes
36 #include "Tpm.h"
37 #include "Attest_spt_fp.h"
38
39 //** Functions
40
41 //***FillInAttestInfo()
42 // Fill in common fields of TPMS_ATTEST structure.
43 void
FillInAttestInfo(TPMI_DH_OBJECT signHandle,TPMT_SIG_SCHEME * scheme,TPM2B_DATA * data,TPMS_ATTEST * attest)44 FillInAttestInfo(
45 TPMI_DH_OBJECT signHandle, // IN: handle of signing object
46 TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing
47 TPM2B_DATA *data, // IN: qualifying data
48 TPMS_ATTEST *attest // OUT: attest structure
49 )
50 {
51 OBJECT *signObject = HandleToObject(signHandle);
52
53 // Magic number
54 attest->magic = TPM_GENERATED_VALUE;
55
56 if(signObject == NULL)
57 {
58 // The name for a null handle is TPM_RH_NULL
59 // This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the
60 // size of the cast is smaller than a constant, the compiler warns
61 // about the truncation of a constant value.
62 TPM_HANDLE nullHandle = TPM_RH_NULL;
63 attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE);
64 UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name);
65 }
66 else
67 {
68 // Certifying object qualified name
69 // if the scheme is anonymous, this is an empty buffer
70 if(CryptIsSchemeAnonymous(scheme->scheme))
71 attest->qualifiedSigner.t.size = 0;
72 else
73 attest->qualifiedSigner = signObject->qualifiedName;
74 }
75 // current clock in plain text
76 TimeFillInfo(&attest->clockInfo);
77
78 // Firmware version in plain text
79 attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8));
80 attest->firmwareVersion += gp.firmwareV2;
81
82 // Check the hierarchy of sign object. For NULL sign handle, the hierarchy
83 // will be TPM_RH_NULL
84 if((signObject == NULL)
85 || (!signObject->attributes.epsHierarchy
86 && !signObject->attributes.ppsHierarchy))
87 {
88 // For signing key that is not in platform or endorsement hierarchy,
89 // obfuscate the reset, restart and firmware version information
90 UINT64 obfuscation[2];
91 CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gp.shProof.b, OBFUSCATE_STRING,
92 &attest->qualifiedSigner.b, NULL, 128,
93 (BYTE *)&obfuscation[0], NULL, FALSE);
94 // Obfuscate data
95 attest->firmwareVersion += obfuscation[0];
96 attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
97 attest->clockInfo.restartCount += (UINT32)obfuscation[1];
98 }
99 // External data
100 if(CryptIsSchemeAnonymous(scheme->scheme))
101 attest->extraData.t.size = 0;
102 else
103 {
104 // If we move the data to the attestation structure, then it is not
105 // used in the signing operation except as part of the signed data
106 attest->extraData = *data;
107 data->t.size = 0;
108 }
109 }
110
111 //***SignAttestInfo()
112 // Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature
113 // is returned.
114 //
115 // Return Type: TPM_RC
116 // TPM_RC_ATTRIBUTES 'signHandle' references not a signing key
117 // TPM_RC_SCHEME 'scheme' is not compatible with 'signHandle' type
118 // TPM_RC_VALUE digest generated for the given 'scheme' is greater than
119 // the modulus of 'signHandle' (for an RSA key);
120 // invalid commit status or failed to generate "r" value
121 // (for an ECC key)
122 TPM_RC
SignAttestInfo(OBJECT * signKey,TPMT_SIG_SCHEME * scheme,TPMS_ATTEST * certifyInfo,TPM2B_DATA * qualifyingData,TPM2B_ATTEST * attest,TPMT_SIGNATURE * signature)123 SignAttestInfo(
124 OBJECT *signKey, // IN: sign object
125 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
126 TPMS_ATTEST *certifyInfo, // IN: the data to be signed
127 TPM2B_DATA *qualifyingData, // IN: extra data for the signing
128 // process
129 TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be
130 // signed
131 TPMT_SIGNATURE *signature // OUT: signature
132 )
133 {
134 BYTE *buffer;
135 HASH_STATE hashState;
136 TPM2B_DIGEST digest;
137 TPM_RC result;
138
139 // Marshal TPMS_ATTEST structure for hash
140 buffer = attest->t.attestationData;
141 attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL);
142
143 if(signKey == NULL)
144 {
145 signature->sigAlg = TPM_ALG_NULL;
146 result = TPM_RC_SUCCESS;
147 }
148 else
149 {
150 TPMI_ALG_HASH hashAlg;
151 // Compute hash
152 hashAlg = scheme->details.any.hashAlg;
153 // need to set the receive buffer to get something put in it
154 digest.t.size = sizeof(digest.t.buffer);
155 digest.t.size = CryptHashBlock(hashAlg, attest->t.size,
156 attest->t.attestationData,
157 digest.t.size, digest.t.buffer);
158 // If there is qualifying data, need to rehash the data
159 // hash(qualifyingData || hash(attestationData))
160 if(qualifyingData->t.size != 0)
161 {
162 CryptHashStart(&hashState, hashAlg);
163 CryptDigestUpdate2B(&hashState, &qualifyingData->b);
164 CryptDigestUpdate2B(&hashState, &digest.b);
165 CryptHashEnd2B(&hashState, &digest.b);
166 }
167 // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
168 // TPM_RC_ATTRIBUTES error may be returned at this point
169 result = CryptSign(signKey, scheme, &digest, signature);
170
171 // Since the clock is used in an attestation, the state in NV is no longer
172 // "orderly" with respect to the data in RAM if the signature is valid
173 if(result == TPM_RC_SUCCESS)
174 {
175 // Command uses the clock so need to clear the orderly state if it is
176 // set.
177 result = NvClearOrderly();
178 }
179 }
180 return result;
181 }
182
183 //*** IsSigningObject()
184 // Checks to see if the object is OK for signing. This is here rather than in
185 // Object_spt.c because all the attestation commands use this file but not
186 // Object_spt.c.
187 // Return Type: BOOL
188 // TRUE(1) object may sign
189 // FALSE(0) object may not sign
190 BOOL
IsSigningObject(OBJECT * object)191 IsSigningObject(
192 OBJECT *object // IN:
193 )
194 {
195 return ((object == NULL)
196 || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
197 && object->publicArea.type != TPM_ALG_SYMCIPHER)));
198 }