chunk_t pcr_comp;
chunk_t tpm_quote_sign;
chunk_t evid_sign;
- bool evid_signature_included;
+ bool evid_signature_included = FALSE, use_quote2 = FALSE,
+ ver_info_included = FALSE;
+ chunk_t pcr_composite, quote_info;
attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
evid_signature_included = attr_cast->is_evid_sign_included(attr_cast);
*/
composite_algorithm = attr_cast->get_comp_hash_algorithm(attr_cast);
- if ((flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2) ||
- (flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2_CAP_VER))
+ if (flags != PTS_SIMPLE_EVID_FINAL_FLAG_NO)
{
- DBG1(DBG_IMV, "This version of Attestation IMV can not handle"
- " TPM Quote Info2 structure");
- break;
- }
- if (flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO)
- {
- chunk_t pcr_composite, quote_info;
+ if ((flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2) ||
+ (flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2_CAP_VER))
+ {
+ use_quote2 = TRUE;
+ }
+ if (flags == PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2_CAP_VER)
+ {
+ ver_info_included = TRUE;
+ }
+
pcr_comp = attr_cast->get_pcr_comp(attr_cast);
tpm_quote_sign = attr_cast->get_tpm_quote_sign(attr_cast);
DBG1(DBG_IMV, "Either PCR Composite or Quote Signature missing");
return FALSE;
}
-
- /* Construct PCR Composite and TPM Quote Info structures*/
- if (!pts->get_quote_info(pts, composite_algorithm,
- &pcr_composite, "e_info))
+
+ /* Construct PCR Composite and TPM Quote Info structures */
+ if (!pts->get_quote_info(pts, use_quote2, ver_info_included,
+ composite_algorithm, &pcr_composite, "e_info))
{
DBG1(DBG_IMV, "unable to contruct TPM Quote Info");
return FALSE;
}
-
+
/* Check calculated PCR composite matches with received */
if (!chunk_equals(pcr_comp, pcr_composite))
{
}
DBG2(DBG_IMV, "received PCR Composite matches with constructed");
chunk_clear(&pcr_composite);
-
+
if (!pts->verify_quote_signature(pts, quote_info, tpm_quote_sign))
{
chunk_clear("e_info);
return FALSE;
}
-
+
DBG2(DBG_IMV, "signature verification succeeded for "
"TPM Quote Info");
chunk_clear("e_info);
}
-
+
if (evid_signature_included)
{
/** TODO: What to do with Evidence Signature */
}
METHOD(pts_t, quote_tpm, bool,
- private_pts_t *this, u_int32_t *pcrs, u_int32_t num_of_pcrs,
+ private_pts_t *this, bool use_quote2,
+ u_int32_t *pcrs, u_int32_t num_of_pcrs,
chunk_t *pcr_composite, chunk_t *quote_signature)
{
TSS_HCONTEXT hContext;
BYTE secret[] = TSS_WELL_KNOWN_SECRET;
TSS_HPCRS hPcrComposite;
TSS_VALIDATION valData;
- u_int32_t i;
+ u_int32_t i, versionInfoSize;
TSS_RESULT result;
chunk_t pcr_comp, quote_sign;
+ BYTE* versionInfo;
result = Tspi_Context_Create(&hContext);
if (result != TSS_SUCCESS)
}
/* Create PCR composite object */
- result = Tspi_Context_CreateObject(hContext,
- TSS_OBJECT_TYPE_PCRS, 0, &hPcrComposite);
+ result = use_quote2 ?
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ TSS_PCRS_STRUCT_INFO_SHORT, &hPcrComposite) :
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ 0, &hPcrComposite);
if (result != TSS_SUCCESS)
{
goto err2;
DBG1(DBG_PTS, "Invalid PCR number: %d", pcrs[i]);
goto err3;
}
- result = Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcrs[i]);
+ result = use_quote2 ?
+ Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcrs[i],
+ TSS_PCRS_DIRECTION_RELEASE):
+ Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcrs[i]);
if (result != TSS_SUCCESS)
{
goto err3;
/* TPM Quote */
- result = Tspi_TPM_Quote(hTPM, hAIK, hPcrComposite, &valData);
+ result = use_quote2 ?
+ Tspi_TPM_Quote2(hTPM, hAIK, FALSE, hPcrComposite, &valData,
+ &versionInfoSize,&versionInfo):
+ Tspi_TPM_Quote(hTPM, hAIK, hPcrComposite, &valData);
if (result != TSS_SUCCESS)
{
goto err4;
/* Set output chunks */
pcr_comp = chunk_alloc(HASH_SIZE_SHA1);
- memcpy(pcr_comp.ptr, valData.rgbData + 8, HASH_SIZE_SHA1);
+ if (use_quote2)
+ {
+ /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
+ memcpy(pcr_comp.ptr, valData.rgbData + valData.ulDataLength - HASH_SIZE_SHA1,
+ HASH_SIZE_SHA1);
+ }
+ else
+ {
+ /* TPM_Composite_Hash is 8-28th bytes of TPM_Quote_Info structure */
+ memcpy(pcr_comp.ptr, valData.rgbData + 8, HASH_SIZE_SHA1);
+ }
+
*pcr_composite = pcr_comp;
*pcr_composite = chunk_clone(*pcr_composite);
DBG3(DBG_PTS, "Hash of PCR Composite: %B",pcr_composite);
valData.ulValidationDataLength);
*quote_signature = quote_sign;
*quote_signature = chunk_clone(*quote_signature);
- DBG3(DBG_PTS, "TOM Quote Signature: %B",quote_signature);
+ DBG3(DBG_PTS, "TPM Quote Signature: %B",quote_signature);
chunk_clear("e_sign);
Tspi_Context_FreeMemory(hContext, NULL);
}
/**
- * 1. build a TCPA_PCR_COMPOSITE structure which contains (pcrCompositeBuf)
- * TCPA_PCR_SELECTION structure (bitmask length + bitmask)
- * UINT32 (network order) gives the number of bytes following (pcr entries * 20)
- * TCPA_PCRVALUE[] with the pcr values
- *
- * The first two bytes of the message represent the length
- * of the bitmask that follows. The bitmask represents the
- * requested PCRs to be quoted.
- *
- * TPM Main-Part 2 TPM Structures_v1.2 8.1
- * The bitmask is in big endian order"
- *
- * BYTE 1 BYTE 2 ...
- * Bit: 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ...
- * Pcr: 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 ...
- *
- * 2. SHA1(pcrCompositeBuf)
- *
- * 3. build a TCPA_QUOTE_INFO structure which contains
+ * TPM_QUOTE_INFO structure:
* 4 bytes of version
* 4 bytes 'Q' 'U' 'O' 'T'
* 20 byte SHA1 of TCPA_PCR_COMPOSITE
* 20 byte nonce
+ *
+ * TPM_QUOTE_INFO2 structure:
+ * 2 bytes Tag 0x0036 TPM_Tag_Quote_info2
+ * 4 bytes 'Q' 'U' 'T' '2'
+ * 20 bytes nonce
+ * 26 bytes PCR_INFO_SHORT
*/
METHOD(pts_t, get_quote_info, bool,
- private_pts_t *this, pts_meas_algorithms_t composite_algo,
+ private_pts_t *this, bool use_quote2, bool ver_info_included,
+ pts_meas_algorithms_t composite_algo,
chunk_t *out_pcr_composite, chunk_t *out_quote_info)
{
enumerator_t *e;
"TPM Quote Info");
return FALSE;
}
+ if (!this->secret.ptr)
+ {
+ DBG1(DBG_PTS, "Secret assessment value unavailable",
+ "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+ if (use_quote2 && ver_info_included && !this->tpm_version_info.ptr)
+ {
+ DBG1(DBG_PTS, "TPM Version Information unavailable",
+ "unable to construct TPM Quote Info2");
+ return FALSE;
+ }
bitmask_len = maximum_pcr_index/8 +1;
u_int8_t mask_bytes[MAX_NUM_PCR/8] = {0};
DBG3(DBG_PTS, "PCR Composite: %B", &pcr_composite);
writer->destroy(writer);
- writer = bio_writer_create(TPM_QUOTE_INFO_LEN);
- /* Version number */
- writer->write_uint8(writer, 1);
- writer->write_uint8(writer, 1);
- writer->write_uint8(writer, 0);
- writer->write_uint8(writer, 0);
-
- /* Magic QUOT value, depends on TPM Ordinal */
- writer->write_uint8(writer, 'Q');
- writer->write_uint8(writer, 'U');
- writer->write_uint8(writer, 'O');
- writer->write_uint8(writer, 'T');
-
/* Output the TPM_PCR_COMPOSITE expected from IMC */
if (composite_algo)
{
hasher->allocate_hash(hasher, pcr_composite, &hash_pcr_composite);
hasher->destroy(hasher);
- writer->write_data(writer, hash_pcr_composite);
- chunk_clear(&pcr_composite);
- chunk_clear(&hash_pcr_composite);
+ /* Construct TPM_QUOTE_INFO/TPM_QUOTE_INFO2 structure */
+ writer = bio_writer_create(TPM_QUOTE_INFO_LEN);
- if (!this->secret.ptr)
+ if (use_quote2)
{
- DBG1(DBG_PTS, "Secret assessment value unavailable",
- "unable to construct TPM Quote Info");
- chunk_clear(out_pcr_composite);
- writer->destroy(writer);
- return FALSE;
+ /* TPM Structure Tag */
+ writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2);
+
+ /* Magic QUT2 value */
+ writer->write_uint8(writer, 'Q');
+ writer->write_uint8(writer, 'U');
+ writer->write_uint8(writer, 'T');
+ writer->write_uint8(writer, '2');
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
+
+ /* Lenght of the bist mask field */
+ writer->write_uint16(writer, bitmask_len);
+
+ /* PCR selection Bitmask */
+ for (i = 0; i< bitmask_len ; i++)
+ {
+ writer->write_uint8(writer, mask_bytes[i]);
+ }
+
+ /* TPM Locality Selection */
+ writer->write_uint8(writer, TPM_LOC_ZERO);
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_composite);
+
+ if (ver_info_included)
+ {
+ /* TPM version Info */
+ writer->write_data(writer, this->tpm_version_info);
+ }
+ }
+ else
+ {
+ /* Version number */
+ writer->write_uint8(writer, 1);
+ writer->write_uint8(writer, 1);
+ writer->write_uint8(writer, 0);
+ writer->write_uint8(writer, 0);
+
+ /* Magic QUOT value */
+ writer->write_uint8(writer, 'Q');
+ writer->write_uint8(writer, 'U');
+ writer->write_uint8(writer, 'O');
+ writer->write_uint8(writer, 'T');
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_composite);
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
}
- /* Secret assessment value 20 bytes (nonce) */
- writer->write_data(writer, this->secret);
+
+ chunk_clear(&pcr_composite);
+ chunk_clear(&hash_pcr_composite);
+
/* TPM Quote Info */
*out_quote_info = chunk_clone(writer->get_buf(writer));
DBG3(DBG_PTS, "Calculated TPM Quote Info: %B", out_quote_info);