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 25 TSS_RESULT 26 Tspi_TPM_Quote(TSS_HTPM hTPM, /* in */ 27 TSS_HKEY hIdentKey, /* in */ 28 TSS_HPCRS hPcrComposite, /* in */ 29 TSS_VALIDATION * pValidationData) /* in, out */ 30 { 31 TCPA_RESULT result; 32 TPM_AUTH privAuth; 33 TPM_AUTH *pPrivAuth = &privAuth; 34 UINT64 offset; 35 TCPA_DIGEST digest; 36 TCS_KEY_HANDLE tcsKeyHandle; 37 TSS_HPOLICY hPolicy; 38 TCPA_NONCE antiReplay; 39 UINT32 pcrDataSize; 40 BYTE pcrData[128]; 41 UINT32 validationLength = 0; 42 BYTE *validationData = NULL; 43 UINT32 pcrDataOutSize; 44 BYTE *pcrDataOut; 45 UINT32 keyDataSize; 46 BYTE *keyData; 47 TSS_KEY keyContainer; 48 BYTE quoteinfo[1024]; 49 TSS_BOOL usesAuth; 50 TSS_HCONTEXT tspContext; 51 TCPA_VERSION version = {1, 1, 0, 0}; 52 Trspi_HashCtx hashCtx; 53 54 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext))) 55 return result; 56 57 if (hPcrComposite && !obj_is_pcrs(hPcrComposite)) 58 return TSPERR(TSS_E_INVALID_HANDLE); 59 60 /* get the identKey Policy */ 61 if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &usesAuth))) 62 return result; 63 64 /* get the Identity TCS keyHandle */ 65 if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle))) 66 return result; 67 68 if (pValidationData == NULL) { 69 if ((result = get_local_random(tspContext, FALSE, sizeof(TCPA_NONCE), 70 (BYTE **)antiReplay.nonce))) 71 return result; 72 } else { 73 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce)) 74 return TSPERR(TSS_E_BAD_PARAMETER); 75 76 memcpy(antiReplay.nonce, pValidationData->rgbExternalData, 77 sizeof(antiReplay.nonce)); 78 } 79 80 pcrDataSize = 0; 81 if (hPcrComposite) { 82 if ((result = obj_pcrs_get_selection(hPcrComposite, &pcrDataSize, pcrData))) 83 return result; 84 } 85 86 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 87 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote); 88 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce); 89 result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData); 90 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 91 return result; 92 93 if (usesAuth) { 94 if ((result = secret_PerformAuth_OIAP(hIdentKey, TPM_ORD_Quote, hPolicy, FALSE, 95 &digest, &privAuth))) { 96 return result; 97 } 98 pPrivAuth = &privAuth; 99 } else { 100 pPrivAuth = NULL; 101 } 102 103 if ((result = TCS_API(tspContext)->Quote(tspContext, tcsKeyHandle, &antiReplay, pcrDataSize, 104 pcrData, pPrivAuth, &pcrDataOutSize, &pcrDataOut, 105 &validationLength, &validationData))) 106 return result; 107 108 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 109 result |= Trspi_Hash_UINT32(&hashCtx, result); 110 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote); 111 result |= Trspi_HashUpdate(&hashCtx, pcrDataOutSize, pcrDataOut); 112 result |= Trspi_Hash_UINT32(&hashCtx, validationLength); 113 result |= Trspi_HashUpdate(&hashCtx, validationLength, validationData); 114 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 115 return result; 116 117 if (usesAuth == TRUE) { 118 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &privAuth))) { 119 free(pcrDataOut); 120 free(validationData); 121 return result; 122 } 123 } 124 125 if (hPcrComposite) { 126 TCPA_PCR_COMPOSITE pcrComp; 127 128 offset = 0; 129 if ((result = Trspi_UnloadBlob_PCR_COMPOSITE(&offset, pcrDataOut, &pcrComp))) { 130 free(pcrDataOut); 131 free(validationData); 132 return result; 133 } 134 135 if ((result = obj_pcrs_set_values(hPcrComposite, &pcrComp))) { 136 free(pcrDataOut); 137 free(validationData); 138 return result; 139 } 140 } 141 142 if ((result = Tspi_GetAttribData(hIdentKey, TSS_TSPATTRIB_KEY_BLOB, 143 TSS_TSPATTRIB_KEYBLOB_BLOB, &keyDataSize, &keyData))) { 144 free(pcrDataOut); 145 free(validationData); 146 return result; 147 } 148 149 /* create the validation data */ 150 offset = 0; 151 memset(&keyContainer, 0, sizeof(TSS_KEY)); 152 if ((result = UnloadBlob_TSS_KEY(&offset, keyData, &keyContainer))) 153 return result; 154 155 /* creating pcrCompositeHash */ 156 Trspi_Hash(TSS_HASH_SHA1, pcrDataOutSize, pcrDataOut, digest.digest); 157 free(pcrDataOut); 158 159 /* generate Quote_info struct */ 160 /* 1. add version */ 161 offset = 0; 162 if (keyContainer.hdr.key12.tag == TPM_TAG_KEY12) 163 Trspi_LoadBlob_TCPA_VERSION(&offset, quoteinfo, version); 164 else 165 Trspi_LoadBlob_TCPA_VERSION(&offset, quoteinfo, keyContainer.hdr.key11.ver); 166 /* 2. add "QUOT" */ 167 quoteinfo[offset++] = 'Q'; 168 quoteinfo[offset++] = 'U'; 169 quoteinfo[offset++] = 'O'; 170 quoteinfo[offset++] = 'T'; 171 /* 3. Composite Hash */ 172 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo, 173 digest.digest); 174 /* 4. AntiReplay Nonce */ 175 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo, 176 antiReplay.nonce); 177 178 if (pValidationData == NULL) { 179 /* validate the data here */ 180 Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest); 181 182 if ((result = Trspi_Verify(TSS_HASH_SHA1, digest.digest, 20, 183 keyContainer.pubKey.key, 184 keyContainer.pubKey.keyLength, 185 validationData, 186 validationLength))) { 187 free_key_refs(&keyContainer); 188 free(validationData); 189 return result; 190 } 191 free_key_refs(&keyContainer); 192 } else { 193 free_key_refs(&keyContainer); 194 195 pValidationData->rgbValidationData = calloc_tspi(tspContext, validationLength); 196 if (pValidationData->rgbValidationData == NULL) { 197 LogError("malloc of %u bytes failed.", validationLength); 198 return TSPERR(TSS_E_OUTOFMEMORY); 199 } 200 pValidationData->ulValidationDataLength = validationLength; 201 memcpy(pValidationData->rgbValidationData, validationData, validationLength); 202 free(validationData); 203 204 pValidationData->rgbData = calloc_tspi(tspContext, offset); 205 if (pValidationData->rgbData == NULL) { 206 LogError("malloc of %" PRIu64 " bytes failed.", offset); 207 free_tspi(tspContext, pValidationData->rgbValidationData); 208 pValidationData->rgbValidationData = NULL; 209 pValidationData->ulValidationDataLength = 0; 210 return TSPERR(TSS_E_OUTOFMEMORY); 211 } 212 pValidationData->ulDataLength = (UINT32)offset; 213 memcpy(pValidationData->rgbData, quoteinfo, offset); 214 } 215 216 return TSS_SUCCESS; 217 } 218