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