1 2 /* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004-2007 8 * 9 */ 10 11 #include <stdlib.h> 12 #include <stdio.h> 13 #include <string.h> 14 #include <inttypes.h> 15 16 #include "trousers/tss.h" 17 #include "trousers/trousers.h" 18 #include "trousers_types.h" 19 #include "spi_utils.h" 20 #include "capabilities.h" 21 #include "tsplog.h" 22 #include "obj.h" 23 24 TSS_RESULT 25 Tspi_TPM_Quote2(TSS_HTPM hTPM, // in 26 TSS_HKEY hIdentKey, // in 27 TSS_BOOL fAddVersion, // in 28 TSS_HPCRS hPcrComposite, // in 29 TSS_VALIDATION* pValidationData, // in, out 30 UINT32* versionInfoSize, // out 31 BYTE** versionInfo) // out 32 { 33 TPM_RESULT result; 34 TSS_HCONTEXT tspContext; 35 TPM_AUTH privAuth; 36 TPM_AUTH *pPrivAuth = &privAuth; 37 UINT64 offset; 38 TPM_DIGEST digest; 39 TSS_BOOL usesAuth; 40 TCS_KEY_HANDLE tcsKeyHandle; 41 TSS_HPOLICY hPolicy; 42 TPM_NONCE antiReplay; 43 UINT32 pcrDataSize; 44 BYTE pcrData[128]; 45 UINT32 sigSize = 0; 46 BYTE *sig = NULL; 47 UINT32 pcrDataOutSize; 48 BYTE *pcrDataOut; 49 BYTE quoteinfo[1024]; 50 Trspi_HashCtx hashCtx; 51 52 LogDebug("Tspi_TPM_Quote2 Start:"); 53 54 /* Takes the context that this TPM handle is on */ 55 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 56 return result; 57 58 /* Test if the hPcrComposite is valid */ 59 if ((hPcrComposite) && !obj_is_pcrs(hPcrComposite)) 60 return TSPERR(TSS_E_INVALID_HANDLE); 61 62 /* get the identKey Policy */ 63 if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &usesAuth))) 64 return result; 65 66 /* get the Identity TCS keyHandle */ 67 if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle))) 68 return result; 69 70 /* Sets the validation data - if NULL, TSS provides it's own random value. If 71 * not NULL, takes the validation external data and sets the antiReplay data 72 * with this */ 73 if (pValidationData == NULL) { 74 LogDebug("Internal Verify:"); 75 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE), 76 (BYTE **)antiReplay.nonce))) 77 return result; 78 } else { 79 LogDebug("External Verify:"); 80 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce)) 81 return TSPERR(TSS_E_BAD_PARAMETER); 82 83 memcpy(antiReplay.nonce, pValidationData->rgbExternalData, 84 sizeof(antiReplay.nonce)); 85 } 86 87 /* Create the TPM_PCR_COMPOSITE object */ 88 pcrDataSize = 0; 89 if (hPcrComposite) { 90 /* Load the PCR Selection Object into the pcrData */ 91 if ((result = obj_pcrs_get_selection(hPcrComposite, &pcrDataSize, pcrData))) 92 return result; 93 } 94 95 if (usesAuth) { 96 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 97 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote2); 98 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce); 99 result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData); 100 result |= Trspi_Hash_BOOL(&hashCtx,fAddVersion); 101 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 102 return result; 103 if ((result = secret_PerformAuth_OIAP(hIdentKey, TPM_ORD_Quote2, hPolicy, FALSE, 104 &digest, &privAuth))) { 105 return result; 106 } 107 pPrivAuth = &privAuth; 108 } else { 109 pPrivAuth = NULL; 110 } 111 112 /* Send to TCS */ 113 if ((result = TCS_API(tspContext)->Quote2(tspContext, tcsKeyHandle, &antiReplay, 114 pcrDataSize, pcrData, fAddVersion, pPrivAuth, 115 &pcrDataOutSize, &pcrDataOut, versionInfoSize, 116 versionInfo, &sigSize, &sig))) 117 return result; 118 119 #ifdef TSS_DEBUG 120 LogDebug("Got TCS Response:"); 121 LogDebug(" pcrDataOutSize: %u",pcrDataOutSize); 122 LogDebug(" pcrDataOut:"); 123 LogDebugData(pcrDataOutSize,pcrDataOut); 124 LogDebug(" versionInfoSize: %u",*versionInfoSize); 125 LogDebug(" versionInfo:"); 126 if (*versionInfoSize >0) 127 LogDebugData(*versionInfoSize,*versionInfo); 128 LogDebug(" sigSize: %u",sigSize); 129 LogDebug(" sig:"); 130 LogDebugData(sigSize,sig); 131 #endif 132 133 if (usesAuth) { 134 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 135 result |= Trspi_Hash_UINT32(&hashCtx, result); 136 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote2); 137 result |= Trspi_HashUpdate(&hashCtx, pcrDataOutSize, pcrDataOut); 138 result |= Trspi_Hash_UINT32(&hashCtx,*versionInfoSize); 139 if (*versionInfoSize > 0) 140 result |= Trspi_HashUpdate(&hashCtx, *versionInfoSize,*versionInfo); 141 result |= Trspi_Hash_UINT32(&hashCtx, sigSize); 142 result |= Trspi_HashUpdate(&hashCtx, sigSize, sig); 143 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { 144 free(pcrDataOut); 145 if (*versionInfoSize > 0) 146 free(*versionInfo); 147 free(sig); 148 return result; 149 } 150 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &privAuth))) { 151 free(pcrDataOut); 152 if (*versionInfoSize > 0) 153 free(*versionInfo); 154 free(sig); 155 return result; 156 } 157 } 158 159 /* Set the pcrDataOut back to the TSS */ 160 if (hPcrComposite){ 161 TPM_PCR_INFO_SHORT pcrInfo; 162 163 offset = 0; 164 if ((result = Trspi_UnloadBlob_PCR_INFO_SHORT(&offset, pcrDataOut, &pcrInfo))) { 165 free(pcrDataOut); 166 if (*versionInfoSize > 0) 167 free(*versionInfo); 168 free(sig); 169 return result; 170 } 171 172 /* Set both digestAtRelease and localityAtRelease */ 173 if ((result = obj_pcrs_set_locality(hPcrComposite, pcrInfo.localityAtRelease))) { 174 free(pcrDataOut); 175 if (*versionInfoSize > 0) 176 free(*versionInfo); 177 free(sig); 178 return result; 179 } 180 181 if ((result = obj_pcrs_set_digest_at_release(hPcrComposite, 182 pcrInfo.digestAtRelease))) { 183 free(pcrDataOut); 184 if (*versionInfoSize > 0) 185 free(*versionInfo); 186 free(sig); 187 return result; 188 } 189 } 190 191 /* generate TPM_QUOTE_INFO2 struct */ 192 memset("einfo, 0, sizeof(quoteinfo)); 193 offset = 0; 194 /* 1. Add Structure TAG */ 195 quoteinfo[offset++] = 0x00; 196 quoteinfo[offset++] = (BYTE) TPM_TAG_QUOTE_INFO2; 197 198 /* 2. add "QUT2" */ 199 quoteinfo[offset++]='Q'; 200 quoteinfo[offset++]='U'; 201 quoteinfo[offset++]='T'; 202 quoteinfo[offset++]='2'; 203 204 /* 3. AntiReplay Nonce - add the external data*/ 205 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo, 206 antiReplay.nonce); 207 /* 4. add the infoshort TPM_PCR_INFO_SHORT data */ 208 Trspi_LoadBlob(&offset,pcrDataOutSize,quoteinfo,pcrDataOut); 209 free(pcrDataOut); 210 211 if (fAddVersion) 212 Trspi_LoadBlob(&offset,*versionInfoSize,quoteinfo,*versionInfo); 213 else { 214 /* versionInfo was not allocated and versionInfoSize has invalid value */ 215 *versionInfoSize = 0; 216 *versionInfo = NULL; 217 } 218 219 LogDebug("TPM_QUOTE_INFO2 data: "); 220 LogDebugData(offset,quoteinfo); 221 222 if (pValidationData == NULL) { 223 if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest))) { 224 free(sig); 225 if (*versionInfoSize > 0) 226 free(*versionInfo); 227 return result; 228 } 229 if ((result = __tspi_rsa_verify(hIdentKey,TSS_HASH_SHA1,sizeof(digest.digest), 230 digest.digest, sigSize, sig))) { 231 free(sig); 232 if (*versionInfoSize > 0) 233 free(*versionInfo); 234 return TSPERR(TSS_E_VERIFICATION_FAILED); 235 } 236 free(sig); 237 } else { 238 pValidationData->rgbValidationData = calloc_tspi(tspContext, sigSize); 239 if (pValidationData->rgbValidationData == NULL) { 240 LogError("malloc of %u bytes failed.", sigSize); 241 free(sig); 242 if (*versionInfoSize > 0) 243 free(*versionInfo); 244 return TSPERR(TSS_E_OUTOFMEMORY); 245 } 246 pValidationData->ulValidationDataLength = sigSize; 247 memcpy(pValidationData->rgbValidationData, sig, sigSize); 248 free(sig); 249 250 pValidationData->rgbData = calloc_tspi(tspContext, offset); 251 if (pValidationData->rgbData == NULL) { 252 LogError("malloc of %" PRIu64 " bytes failed.", offset); 253 free_tspi(tspContext, pValidationData->rgbValidationData); 254 pValidationData->rgbValidationData = NULL; 255 pValidationData->ulValidationDataLength = 0; 256 if (*versionInfoSize > 0) 257 free(*versionInfo); 258 return TSPERR(TSS_E_OUTOFMEMORY); 259 } 260 pValidationData->ulDataLength = (UINT32)offset; 261 memcpy(pValidationData->rgbData, quoteinfo, offset); 262 } 263 264 265 if(*versionInfoSize > 0) { 266 if(fAddVersion) { 267 /* tag versionInfo so that it can be free'd by the app through Tspi_Context_FreeMemory */ 268 if ((result = __tspi_add_mem_entry(tspContext, *versionInfo))) { 269 free_tspi(tspContext, pValidationData->rgbValidationData); 270 pValidationData->rgbValidationData = NULL; 271 pValidationData->ulValidationDataLength = 0; 272 free_tspi(tspContext, pValidationData->rgbData); 273 pValidationData->rgbData = NULL; 274 pValidationData->ulDataLength = 0; 275 free(*versionInfo); 276 return result; 277 } 278 } 279 else { 280 free(*versionInfo); 281 } 282 } 283 284 LogDebug("Tspi_TPM_Quote2 End"); 285 return TSS_SUCCESS; 286 } 287