From: Sansar Choinyambuu Date: Fri, 11 Nov 2011 10:19:46 +0000 (+0100) Subject: Implemented TPM_Quote2 on imc and constructing TPM_Quote_Info2 on imv X-Git-Tag: 4.6.2~208 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f6aab3cd1edb67599dc3eeecdef706a97cea0aa5;p=thirdparty%2Fstrongswan.git Implemented TPM_Quote2 on imc and constructing TPM_Quote_Info2 on imv --- diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c index f91d8d8f5c..8ff68e1e5f 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c @@ -60,7 +60,7 @@ static u_int8_t* string_to_bytearray(char *str_value) for (i = 0; i < strlen(str_value)/2; i++) { char c1, c2; - u_int8_t d1, d2; + u_int8_t d1 = 0, d2 = 0; c1 = str_value[i*2]; c2 = str_value[i*2 + 1]; @@ -547,6 +547,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, chunk_t pcr_composite, quote_signature; u_int32_t num_of_evidences, i = 0; u_int32_t *pcrs; + bool use_quote2; /* Send buffered Simple Component Evidences */ num_of_evidences = evidences->get_count(evidences); @@ -568,9 +569,13 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, /* Send Simple Compoenent Evidence */ attr_list->insert_last(attr_list, attr); } + + use_quote2 = (lib->settings->get_int(lib->settings, + "libimcv.plugins.imc-attestation.quote_version", 1) == 1) ? + FALSE : TRUE; /* Quote */ - if (!pts->quote_tpm(pts, pcrs, num_of_evidences, + if (!pts->quote_tpm(pts, use_quote2, pcrs, num_of_evidences, &pcr_composite, "e_signature)) { DBG1(DBG_IMC, "error occured during TPM quote operation"); @@ -580,7 +585,8 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, } /* Send Simple Evidence Final attribute */ - flags = PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO; + flags = use_quote2 ? PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO2: + PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO; composite_algorithm |= PTS_MEAS_ALGO_SHA1; attr = tcg_pts_attr_simple_evid_final_create(FALSE, flags, diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_process.c b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c index 5e6f8bc8de..5c9cb987db 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation_process.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c @@ -281,7 +281,9 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, 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); @@ -293,16 +295,18 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, */ 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); @@ -313,15 +317,15 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, 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)) { @@ -333,18 +337,18 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, } 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 */ diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 504ef08b2a..178ba64019 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -792,7 +792,8 @@ METHOD(pts_t, extend_pcr, bool, } 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; @@ -804,9 +805,10 @@ METHOD(pts_t, quote_tpm, bool, 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) @@ -854,8 +856,11 @@ METHOD(pts_t, quote_tpm, bool, } /* 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; @@ -869,7 +874,10 @@ METHOD(pts_t, quote_tpm, bool, 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; @@ -882,7 +890,10 @@ METHOD(pts_t, quote_tpm, bool, /* 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; @@ -890,7 +901,18 @@ METHOD(pts_t, quote_tpm, bool, /* 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); @@ -903,7 +925,7 @@ METHOD(pts_t, quote_tpm, bool, 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); @@ -1012,33 +1034,22 @@ METHOD(pts_t, does_pcr_value_match, bool, } /** - * 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; @@ -1055,6 +1066,18 @@ METHOD(pts_t, get_quote_info, bool, "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}; @@ -1095,19 +1118,6 @@ METHOD(pts_t, get_quote_info, bool, 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) { @@ -1152,20 +1162,68 @@ METHOD(pts_t, get_quote_info, bool, 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); diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index b92bbdc209..b3298b0e4e 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -317,6 +317,7 @@ struct pts_t { * Quote over PCR's * Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK * + * @param use_quote2 Version of the Quote funtion to be used * @param pcrs Array of PCR's to make quotation over * @param num_of_pcrs Number of elements in pcrs array * @param pcr_composite Chunk to save pcr composite structure @@ -324,7 +325,8 @@ struct pts_t { * without external data (anti-replay protection) * @return FALSE in case of TSS error, TRUE otherwise */ - bool (*quote_tpm)(pts_t *this, u_int32_t *pcrs, u_int32_t num_of_pcrs, + bool (*quote_tpm)(pts_t *this, bool use_quote2, + u_int32_t *pcrs, u_int32_t num_of_pcrs, chunk_t *pcr_composite, chunk_t *quote_signature); /** @@ -337,11 +339,14 @@ struct pts_t { /** * Constructs and returns TPM Quote Info structure expected from IMC * - * @param pcr_composite Output variable to store PCR Composite - * @param quote_info Output variable to store TPM Quote Info + * @param use_quote2 Version of the TPM_QUOTE_INFO to be constructed + * @param ver_info_included Version info is concatenated to TPM_QUOTE_INFO2 + * @param pcr_composite Output variable to store PCR Composite + * @param quote_info Output variable to store TPM Quote Info * @return FALSE in case of any error, TRUE otherwise */ - bool (*get_quote_info)(pts_t *this, pts_meas_algorithms_t composite_algo, + bool (*get_quote_info)(pts_t *this, bool use_quote2, bool ver_info_included, + pts_meas_algorithms_t composite_algo, chunk_t *pcr_composite, chunk_t *quote_info); /**