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 free(pcrInfo.pcrSelection.pcrSelect); 167 if (*versionInfoSize > 0) 168 free(*versionInfo); 169 free(sig); 170 return result; 171 } 172 free(pcrInfo.pcrSelection.pcrSelect); 173 174 /* Set both digestAtRelease and localityAtRelease */ 175 if ((result = obj_pcrs_set_locality(hPcrComposite, pcrInfo.localityAtRelease))) { 176 free(pcrDataOut); 177 if (*versionInfoSize > 0) 178 free(*versionInfo); 179 free(sig); 180 return result; 181 } 182 183 if ((result = obj_pcrs_set_digest_at_release(hPcrComposite, 184 pcrInfo.digestAtRelease))) { 185 free(pcrDataOut); 186 if (*versionInfoSize > 0) 187 free(*versionInfo); 188 free(sig); 189 return result; 190 } 191 } 192 193 /* generate TPM_QUOTE_INFO2 struct */ 194 __tspi_memset("einfo, 0, sizeof(quoteinfo)); 195 offset = 0; 196 /* 1. Add Structure TAG */ 197 quoteinfo[offset++] = 0x00; 198 quoteinfo[offset++] = (BYTE) TPM_TAG_QUOTE_INFO2; 199 200 /* 2. add "QUT2" */ 201 quoteinfo[offset++]='Q'; 202 quoteinfo[offset++]='U'; 203 quoteinfo[offset++]='T'; 204 quoteinfo[offset++]='2'; 205 206 /* 3. AntiReplay Nonce - add the external data*/ 207 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo, 208 antiReplay.nonce); 209 /* 4. add the infoshort TPM_PCR_INFO_SHORT data */ 210 Trspi_LoadBlob(&offset,pcrDataOutSize,quoteinfo,pcrDataOut); 211 free(pcrDataOut); 212 213 if (fAddVersion) 214 Trspi_LoadBlob(&offset,*versionInfoSize,quoteinfo,*versionInfo); 215 else { 216 /* versionInfo was not allocated and versionInfoSize has invalid value */ 217 *versionInfoSize = 0; 218 *versionInfo = NULL; 219 } 220 221 LogDebug("TPM_QUOTE_INFO2 data: "); 222 LogDebugData(offset,quoteinfo); 223 224 if (pValidationData == NULL) { 225 if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest))) { 226 free(sig); 227 if (*versionInfoSize > 0) 228 free(*versionInfo); 229 return result; 230 } 231 if ((result = __tspi_rsa_verify(hIdentKey,TSS_HASH_SHA1,sizeof(digest.digest), 232 digest.digest, sigSize, sig))) { 233 free(sig); 234 if (*versionInfoSize > 0) 235 free(*versionInfo); 236 return TSPERR(TSS_E_VERIFICATION_FAILED); 237 } 238 free(sig); 239 } else { 240 pValidationData->rgbValidationData = calloc_tspi(tspContext, sigSize); 241 if (pValidationData->rgbValidationData == NULL) { 242 LogError("malloc of %u bytes failed.", sigSize); 243 free(sig); 244 if (*versionInfoSize > 0) 245 free(*versionInfo); 246 return TSPERR(TSS_E_OUTOFMEMORY); 247 } 248 pValidationData->ulValidationDataLength = sigSize; 249 memcpy(pValidationData->rgbValidationData, sig, sigSize); 250 free(sig); 251 252 pValidationData->rgbData = calloc_tspi(tspContext, offset); 253 if (pValidationData->rgbData == NULL) { 254 LogError("malloc of %" PRIu64 " bytes failed.", offset); 255 free_tspi(tspContext, pValidationData->rgbValidationData); 256 pValidationData->rgbValidationData = NULL; 257 pValidationData->ulValidationDataLength = 0; 258 if (*versionInfoSize > 0) 259 free(*versionInfo); 260 return TSPERR(TSS_E_OUTOFMEMORY); 261 } 262 pValidationData->ulDataLength = (UINT32)offset; 263 memcpy(pValidationData->rgbData, quoteinfo, offset); 264 } 265 266 267 if(*versionInfoSize > 0) { 268 if(fAddVersion && pValidationData) { 269 /* tag versionInfo so that it can be free'd by the app through Tspi_Context_FreeMemory */ 270 if ((result = __tspi_add_mem_entry(tspContext, *versionInfo))) { 271 free_tspi(tspContext, pValidationData->rgbValidationData); 272 pValidationData->rgbValidationData = NULL; 273 pValidationData->ulValidationDataLength = 0; 274 free_tspi(tspContext, pValidationData->rgbData); 275 pValidationData->rgbData = NULL; 276 pValidationData->ulDataLength = 0; 277 free(*versionInfo); 278 return result; 279 } 280 } 281 else { 282 free(*versionInfo); 283 } 284 } 285 286 LogDebug("Tspi_TPM_Quote2 End"); 287 return TSS_SUCCESS; 288 } 289