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 { 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 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