Coverage Report

Created: 2025-10-28 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tpm2/Attest_spt.c
Line
Count
Source
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
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
0
{
33
0
     TPM_RC                         result;
34
0
     TPMI_RH_HIERARCHY              signHierarhcy;
35
0
     result = CryptSelectSignScheme(signHandle, scheme);
36
0
     if(result != TPM_RC_SUCCESS)
37
0
         return result;
38
     // Magic number
39
0
     attest->magic = TPM_GENERATED_VALUE;
40
0
     if(signHandle == TPM_RH_NULL)
41
0
     {
42
0
         BYTE     *buffer;
43
0
         INT32     bufferSize;
44
         // For null sign handle, the QN is TPM_RH_NULL
45
0
         buffer = attest->qualifiedSigner.t.name;
46
0
         bufferSize = sizeof(TPM_HANDLE);
47
0
         attest->qualifiedSigner.t.size =
48
0
              TPM_HANDLE_Marshal(&signHandle, &buffer, &bufferSize);
49
0
     }
50
0
     else
51
0
     {
52
         // Certifying object qualified name
53
         // if the scheme is anonymous, this is an empty buffer
54
0
         if(CryptIsSchemeAnonymous(scheme->scheme))
55
0
              attest->qualifiedSigner.t.size = 0;
56
0
         else
57
0
              ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner);
58
0
   }
59
   // current clock in plain text
60
0
   TimeFillInfo(&attest->clockInfo);
61
   // Firmware version in plain text
62
0
   attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8));
63
0
   attest->firmwareVersion += gp.firmwareV2;
64
   // Get the hierarchy of sign object. For NULL sign handle, the hierarchy
65
   // will be TPM_RH_NULL
66
0
   signHierarhcy = EntityGetHierarchy(signHandle);
67
0
   if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT)
68
0
   {
69
       // For sign object is not in platform or endorsement hierarchy,
70
       // obfuscate the clock and firmwereVersion information
71
0
       UINT64          obfuscation[2];
72
0
       TPMI_ALG_HASH   hashAlg;
73
         // Get hash algorithm
74
0
         if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER)
75
0
         {
76
0
              hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
77
0
         }
78
0
         else
79
0
         {
80
0
              OBJECT          *signObject = NULL;
81
0
              signObject = ObjectGet(signHandle);
82
0
              hashAlg = signObject->publicArea.nameAlg;
83
0
         }
84
0
         KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE",
85
0
               &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL);
86
         // Obfuscate data
87
0
         attest->firmwareVersion += obfuscation[0];
88
0
         attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
89
0
         attest->clockInfo.restartCount += (UINT32)obfuscation[1];
90
0
   }
91
   // External data
92
0
   if(CryptIsSchemeAnonymous(scheme->scheme))
93
0
       attest->extraData.t.size = 0;
94
0
   else
95
0
   {
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
0
       attest->extraData = *data;
99
0
       data->t.size = 0;
100
0
   }
101
0
   return TPM_RC_SUCCESS;
102
0
}
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
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
0
{
131
0
   TPM_RC                         result;
132
0
   TPMI_ALG_HASH                  hashAlg;
133
0
   BYTE                           *buffer;
134
0
   INT32                          bufferSize;
135
0
   HASH_STATE                     hashState;
136
0
   TPM2B_DIGEST                   digest;
137
   // Marshal TPMS_ATTEST structure for hash
138
0
   buffer = attest->t.attestationData;
139
0
   bufferSize = sizeof(TPMS_ATTEST);
140
0
   attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, &bufferSize);
141
0
   if(signHandle == TPM_RH_NULL)
142
0
   {
143
0
       signature->sigAlg = TPM_ALG_NULL;
144
0
   }
145
0
   else
146
0
   {
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
0
       if(gp.orderlyState != SHUTDOWN_NONE)
151
0
       {
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
0
           result = NvIsAvailable();
156
0
           if(result != TPM_RC_SUCCESS)
157
0
               return result;
158
0
       }
159
         // Compute hash
160
0
         hashAlg = scheme->details.any.hashAlg;
161
0
         digest.t.size = CryptStartHash(hashAlg, &hashState);
162
0
         CryptUpdateDigest(&hashState, attest->t.size, attest->t.attestationData);
163
0
         CryptCompleteHash2B(&hashState, &digest.b);
164
         // If there is qualifying data, need to rehash the the data
165
         // hash(qualifyingData || hash(attestationData))
166
0
         if(qualifyingData->t.size != 0)
167
0
         {
168
0
             CryptStartHash(hashAlg, &hashState);
169
0
             CryptUpdateDigest(&hashState,
170
0
                               qualifyingData->t.size,
171
0
                               qualifyingData->t.buffer);
172
0
             CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer);
173
0
             CryptCompleteHash2B(&hashState, &digest.b);
174
0
          }
175
          // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
176
          // TPM_RC_ATTRIBUTES error may be returned at this point
177
0
          return CryptSign(signHandle,
178
0
                           scheme,
179
0
                           &digest,
180
0
                           signature);
181
0
     }
182
0
     return TPM_RC_SUCCESS;
183
0
}