diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-07-21 15:56:39 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-07-21 15:58:13 +0200 |
commit | 4c020862411c1f52154ea5a98507cdfbc5a88e6b (patch) | |
tree | 6818c3e816df42a2af2658b6724f645c360bd3f9 /src/libpts | |
parent | 3b7468b245f2888be57bbf5531b0191b968e2da1 (diff) | |
download | strongswan-4c020862411c1f52154ea5a98507cdfbc5a88e6b.tar.bz2 strongswan-4c020862411c1f52154ea5a98507cdfbc5a88e6b.tar.xz |
moved all shadow PCR stuff to the pts_pcr class
Diffstat (limited to 'src/libpts')
-rw-r--r-- | src/libpts/plugins/imc_attestation/imc_attestation_process.c | 3 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_ima.c | 61 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_tboot.c | 32 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_tgrub.c | 23 | ||||
-rw-r--r-- | src/libpts/pts/pts.c | 234 | ||||
-rw-r--r-- | src/libpts/pts/pts.h | 28 | ||||
-rw-r--r-- | src/libpts/pts/pts_pcr.c | 196 | ||||
-rw-r--r-- | src/libpts/pts/pts_pcr.h | 50 |
8 files changed, 335 insertions, 292 deletions
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_process.c b/src/libpts/plugins/imc_attestation/imc_attestation_process.c index edaaa570f..5ba9f8790 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation_process.c +++ b/src/libpts/plugins/imc_attestation/imc_attestation_process.c @@ -420,9 +420,6 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, /* Send buffered Simple Component Evidences */ while (attestation_state->next_evidence(attestation_state, &evid)) { - pts->select_pcr(pts, evid->get_extended_pcr(evid)); - - /* Send Simple Component Evidence */ attr = tcg_pts_attr_simple_comp_evid_create(evid); attr_list->insert_last(attr_list, attr); } diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c index b687c0f8e..d57fe6a9d 100644 --- a/src/libpts/pts/components/ita/ita_comp_ima.c +++ b/src/libpts/pts/components/ita/ita_comp_ima.c @@ -122,11 +122,6 @@ struct pts_ita_comp_ima_t { linked_list_t *ima_list; /** - * Shadow PCR set - */ - pts_pcr_t *pcrs; - - /** * Whether to send pcr_before and pcr_after info */ bool pcr_info; @@ -361,8 +356,8 @@ static bool load_runtime_measurements(char *file, linked_list_t *list, /** * Extend measurement into PCR an create evidence */ -static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, - chunk_t measurement) +static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, pts_pcr_t *pcrs, + u_int32_t pcr, chunk_t measurement) { size_t pcr_len; pts_pcr_transform_t pcr_transform; @@ -376,9 +371,9 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, if (this->pcr_info) { - pcr_before = chunk_clone(this->pcrs->get(this->pcrs, pcr)); + pcr_before = chunk_clone(pcrs->get(pcrs, pcr)); } - pcr_after = this->pcrs->extend(this->pcrs, pcr, measurement); + pcr_after = pcrs->extend(pcrs, pcr, measurement); if (!pcr_after.ptr) { free(pcr_before.ptr); @@ -389,7 +384,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, this->measurement_time, measurement); if (this->pcr_info) { - pcr_after =chunk_clone(this->pcrs->get(this->pcrs, pcr)); + pcr_after =chunk_clone(pcrs->get(pcrs, pcr)); evidence->set_pcr_info(evidence, pcr_before, pcr_after); } return evidence; @@ -398,7 +393,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, /** * Compute and check boot aggregate value by hashing PCR0 to PCR7 */ -static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement) +static void check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement) { u_int32_t i; u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1]; @@ -415,7 +410,7 @@ static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement) } for (i = 0; i < 8 && pcr_ok; i++) { - pcr_ok = hasher->get_hash(hasher, this->pcrs->get(this->pcrs, i), NULL); + pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL); } if (pcr_ok) { @@ -468,8 +463,10 @@ METHOD(pts_component_t, measure, status_t, status_t status; int count; enumerator_t *e; + pts_pcr_t *pcrs; pts_file_meas_t *file_meas; + pcrs = pts->get_pcrs(pts); *measurements = NULL; switch (this->state) @@ -490,8 +487,8 @@ METHOD(pts_component_t, measure, status_t, DBG1(DBG_PTS, "could not retrieve bios measurement entry"); return status; } - *evidence = extend_pcr(this, bios_entry->pcr, - bios_entry->measurement); + *evidence = extend_pcr(this, pcrs, bios_entry->pcr, + bios_entry->measurement); free(bios_entry); if (!evidence) { @@ -545,11 +542,11 @@ METHOD(pts_component_t, measure, status_t, DBG1(DBG_PTS, "could not retrieve ima measurement entry"); return status; } - *evidence = extend_pcr(this, IMA_PCR, ima_entry->measurement); + *evidence = extend_pcr(this, pcrs, IMA_PCR, ima_entry->measurement); if (this->state == IMA_STATE_BOOT_AGGREGATE) { - check_boot_aggregate(this, ima_entry->measurement); + check_boot_aggregate(pcrs, ima_entry->measurement); } free(ima_entry->file_measurement.ptr); @@ -578,10 +575,12 @@ METHOD(pts_component_t, verify, status_t, enum_name_t *names; pts_meas_algorithms_t algo; pts_pcr_transform_t transform; + pts_pcr_t *pcrs; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; status_t status; + pcrs = pts->get_pcrs(pts); measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); @@ -665,13 +664,25 @@ METHOD(pts_component_t, verify, status_t, has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); if (has_pcr_info) { - if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) + if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr))) + { + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value", + extended_pcr); + } + if (pcrs->set(pcrs, extended_pcr, pcr_after)) { - return FAILED; + return SUCCESS; } } - - return SUCCESS; + else + { + pcr_after = pcrs->extend(pcrs, extended_pcr, measurement); + if (pcr_after.ptr) + { + return SUCCESS; + } + } + return FAILED; } METHOD(pts_component_t, finalize, bool, @@ -723,7 +734,6 @@ METHOD(pts_component_t, destroy, void, this->bios_list->destroy_function(this->bios_list, (void *)free_bios_entry); this->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry); this->name->destroy(this->name); - this->pcrs->destroy(this->pcrs); free(this->keyid.ptr); free(this); } @@ -735,14 +745,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth, pts_database_t *pts_db) { pts_ita_comp_ima_t *this; - pts_pcr_t *pcrs; - - pcrs = pts_pcr_create(); - if (!pcrs) - { - DBG1(DBG_PTS, "shadow PCR set could not be created"); - return NULL; - } INIT(this, .public = { @@ -761,7 +763,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth, .bios_list = linked_list_create(), .ima_list = linked_list_create(), .ima_count = IMA_MEASUREMENT_BATCH_SIZE - 1, - .pcrs = pcrs, .pcr_info = lib->settings->get_bool(lib->settings, "libimcv.plugins.imc-attestation.pcr_info", TRUE), ); diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c index 8ac8335bf..40befc3e0 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.c +++ b/src/libpts/pts/components/ita/ita_comp_tboot.c @@ -110,13 +110,14 @@ METHOD(pts_component_t, measure, status_t, pts_file_meas_t **measurements) { + size_t pcr_len; + pts_pcr_t *pcrs; + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; pts_comp_evidence_t *evid; char *meas_hex, *pcr_before_hex, *pcr_after_hex; chunk_t measurement, pcr_before, pcr_after; - size_t hash_size, pcr_len; u_int32_t extended_pcr; - pts_pcr_transform_t pcr_transform; - pts_meas_algorithms_t hash_algo; switch (this->seq_no++) { @@ -150,9 +151,8 @@ METHOD(pts_component_t, measure, status_t, return FAILED; } - hash_algo = pts->get_meas_algorithm(pts); - hash_size = pts_meas_algo_hash_size(hash_algo); - pcr_len = pts->get_pcr_len(pts); + hash_algo = PTS_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); /* get and check the measurement data */ @@ -163,7 +163,7 @@ METHOD(pts_component_t, measure, status_t, pcr_after = chunk_from_hex( chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL); if (pcr_before.len != pcr_len || pcr_after.len != pcr_len || - measurement.len != hash_size) + measurement.len != pcr_len) { DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size"); free(measurement.ptr); @@ -172,10 +172,11 @@ METHOD(pts_component_t, measure, status_t, return FAILED; } + pcrs = pts->get_pcrs(pts); + pcrs->set(pcrs, extended_pcr, pcr_after); evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name), - this->depth, extended_pcr, - hash_algo, pcr_transform, - this->measurement_time, measurement); + this->depth, extended_pcr, hash_algo, pcr_transform, + this->measurement_time, measurement); evid->set_pcr_info(evid, pcr_before, pcr_after); return (this->seq_no < 2) ? NEED_MORE : SUCCESS; @@ -189,10 +190,12 @@ METHOD(pts_component_t, verify, status_t, enum_name_t *names; pts_meas_algorithms_t algo; pts_pcr_transform_t transform; + pts_pcr_t *pcrs; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; status_t status; + pcrs = pts->get_pcrs(pts); measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); @@ -258,9 +261,14 @@ METHOD(pts_component_t, verify, status_t, has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); if (has_pcr_info) { - if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) + if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr))) { - return FAILED; + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value", + extended_pcr); + } + if (pcrs->set(pcrs, extended_pcr, pcr_after)) + { + return SUCCESS; } } diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c index a25f2f8ab..1d24b0a93 100644 --- a/src/libpts/pts/components/ita/ita_comp_tgrub.c +++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c @@ -73,13 +73,13 @@ METHOD(pts_component_t, measure, status_t, pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence, pts_file_meas_t **measurements) { + size_t pcr_len; + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; pts_comp_evidence_t *evid; u_int32_t extended_pcr; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; - pts_pcr_transform_t pcr_transform; - pts_meas_algorithms_t hash_algo; - size_t hash_size, pcr_len; /* Provisional implementation for TGRUB */ extended_pcr = PCR_DEBUG; @@ -91,12 +91,11 @@ METHOD(pts_component_t, measure, status_t, return FAILED; } - hash_algo = pts->get_meas_algorithm(pts); - hash_size = pts_meas_algo_hash_size(hash_algo); - pcr_len = pts->get_pcr_len(pts); + hash_algo = PTS_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); - measurement = chunk_alloc(hash_size); + measurement = chunk_alloc(pcr_len); memset(measurement.ptr, 0x00, measurement.len); pcr_before = chunk_alloc(pcr_len); @@ -118,9 +117,11 @@ METHOD(pts_component_t, verify, status_t, u_int32_t extended_pcr; pts_meas_algorithms_t algo; pts_pcr_transform_t transform; + pts_pcr_t *pcrs; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; + pcrs = pts->get_pcrs(pts); measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); if (extended_pcr != PCR_DEBUG) @@ -133,9 +134,13 @@ METHOD(pts_component_t, verify, status_t, has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); if (has_pcr_info) { - if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) + if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr))) + { + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value"); + } + if (pcrs->set(pcrs, extended_pcr, pcr_after)) { - return FAILED; + return SUCCESS; } } diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 16047aa08..769890fa3 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -30,16 +30,6 @@ #include <unistd.h> #include <errno.h> -/** - * Maximum number of PCR's of TPM, TPM Spec 1.2 - */ -#define PCR_MAX_NUM 24 - -/** - * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2 - */ -#define PCR_LEN 20 - typedef struct private_pts_t private_pts_t; /** @@ -119,29 +109,9 @@ struct private_pts_t { certificate_t *aik; /** - * Table of extended PCRs with corresponding values - */ - u_char* pcrs[PCR_MAX_NUM]; - - /** - * Length of PCR registers - */ - size_t pcr_len; - - /** - * Number of extended PCR registers + * Shadow PCR set */ - u_int32_t pcr_count; - - /** - * Highest extended PCR register - */ - u_int32_t pcr_max; - - /** - * Bitmap of extended PCR registers - */ - u_int8_t pcr_select[PCR_MAX_NUM / 8]; + pts_pcr_t *pcrs; }; @@ -369,12 +339,6 @@ METHOD(pts_t, set_tpm_version_info, void, print_tpm_version_info(this); } -METHOD(pts_t, get_pcr_len, size_t, - private_pts_t *this) -{ - return this->pcr_len; -} - /** * Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute) */ @@ -715,8 +679,8 @@ METHOD(pts_t, extend_pcr, bool, goto err; } - pcr_value = chunk_alloc(PCR_LEN); - result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr, + pcr_value = chunk_alloc(PTS_PCR_LEN); + result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr, NULL, &pcr_length, &pcr_value.ptr); if (result != TSS_SUCCESS) { @@ -745,22 +709,6 @@ err: return FALSE; } - -static void clear_pcrs(private_pts_t *this) -{ - int i; - - for (i = 0; i <= this->pcr_max; i++) - { - free(this->pcrs[i]); - this->pcrs[i] = NULL; - } - this->pcr_count = 0; - this->pcr_max = 0; - - memset(this->pcr_select, 0x00, sizeof(this->pcr_select)); -} - METHOD(pts_t, quote_tpm, bool, private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig) { @@ -776,7 +724,8 @@ METHOD(pts_t, quote_tpm, bool, TSS_RESULT result; chunk_t quote_info; BYTE* versionInfo; - u_int32_t versionInfoSize, pcr, i = 0, f = 1; + u_int32_t versionInfoSize, pcr; + enumerator_t *enumerator; bool success = FALSE; result = Tspi_Context_Create(&hContext); @@ -836,25 +785,23 @@ METHOD(pts_t, quote_tpm, bool, } /* Select PCRs */ - for (pcr = 0; pcr <= this->pcr_max ; pcr++) - { - if (f == 256) - { - i++; - f = 1; - } - if (this->pcr_select[i] & f) + enumerator = this->pcrs->create_enumerator(this->pcrs); + while (enumerator->enumerate(enumerator, &pcr)) + { + result = use_quote2 ? + Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr, + TSS_PCRS_DIRECTION_RELEASE) : + Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr); + if (result != TSS_SUCCESS) { - result = use_quote2 ? - Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr, - TSS_PCRS_DIRECTION_RELEASE) : - Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr); - if (result != TSS_SUCCESS) - { - goto err3; - } + break; } - f <<= 1; + } + enumerator->destroy(enumerator); + + if (result != TSS_SUCCESS) + { + goto err3; } /* Set the Validation Data */ @@ -914,87 +861,14 @@ err1: { DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result); } - clear_pcrs(this); return success; } -METHOD(pts_t, select_pcr, bool, - private_pts_t *this, u_int32_t pcr) -{ - u_int32_t i, f; - - if (pcr >= PCR_MAX_NUM) - { - DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u", - pcr, PCR_MAX_NUM-1); - return FALSE; - } - - /* Determine PCR selection flag */ - i = pcr / 8; - f = 1 << (pcr - 8*i); - - /* Has this PCR already been selected? */ - if (!(this->pcr_select[i] & f)) - { - this->pcr_select[i] |= f; - this->pcr_max = max(this->pcr_max, pcr); - this->pcr_count++; - } - - return TRUE; -} - -METHOD(pts_t, add_pcr, bool, - private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after) +METHOD(pts_t, get_pcrs, pts_pcr_t*, + private_pts_t *this) { - if (pcr >= PCR_MAX_NUM) - { - DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u", - pcr, PCR_MAX_NUM-1); - return FALSE; - } - - /* Is the length of the PCR registers already set? */ - if (this->pcr_len) - { - if (pcr_after.len != this->pcr_len) - { - DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes", - pcr_after.len, this->pcr_len); - return FALSE; - } - } - else - { - this->pcr_len = pcr_after.len; - } - - /* Has the value of the PCR register already been assigned? */ - if (this->pcrs[pcr]) - { - if (!memeq(this->pcrs[pcr], pcr_before.ptr, this->pcr_len)) - { - DBG1(DBG_PTS, "PCR %02u: new pcr_before value does not equal " - "old pcr_after value"); - } - /* remove the old PCR value */ - free(this->pcrs[pcr]); - } - else - { - /* add extended PCR Register */ - this->pcr_select[pcr / 8] |= 1 << (pcr % 8); - this->pcr_max = max(this->pcr_max, pcr); - this->pcr_count++; - } - - /* Duplicate and store current PCR value */ - pcr_after = chunk_clone(pcr_after); - this->pcrs[pcr] = pcr_after.ptr; - - return TRUE; + return this->pcrs; } /** @@ -1016,13 +890,11 @@ METHOD(pts_t, get_quote_info, bool, pts_meas_algorithms_t comp_hash_algo, chunk_t *out_pcr_comp, chunk_t *out_quote_info) { - u_int8_t size_of_select; - int pcr_comp_len, i; - chunk_t pcr_comp, hash_pcr_comp; + chunk_t selection, pcr_comp, hash_pcr_comp; bio_writer_t *writer; hasher_t *hasher; - if (this->pcr_count == 0) + if (!this->pcrs->get_count(this->pcrs)) { DBG1(DBG_PTS, "No extended PCR entries available, " "unable to construct TPM Quote Info"); @@ -1041,33 +913,8 @@ METHOD(pts_t, get_quote_info, bool, return FALSE; } - /** - * A TPM v1.2 has 24 PCR Registers - * so the bitmask field length used by TrouSerS is at least 3 bytes - */ - size_of_select = max(PCR_MAX_NUM / 8, 1 + this->pcr_max / 8); - pcr_comp_len = 2 + size_of_select + 4 + this->pcr_count * this->pcr_len; - - writer = bio_writer_create(pcr_comp_len); + pcr_comp = this->pcrs->get_composite(this->pcrs); - writer->write_uint16(writer, size_of_select); - for (i = 0; i < size_of_select; i++) - { - writer->write_uint8(writer, this->pcr_select[i]); - } - - writer->write_uint32(writer, this->pcr_count * this->pcr_len); - for (i = 0; i < 8 * size_of_select; i++) - { - if (this->pcrs[i]) - { - writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len)); - } - } - pcr_comp = chunk_clone(writer->get_buf(writer)); - DBG3(DBG_PTS, "constructed PCR Composite: %B", &pcr_comp); - - writer->destroy(writer); /* Output the TPM_PCR_COMPOSITE expected from IMC */ if (comp_hash_algo) @@ -1117,14 +964,10 @@ METHOD(pts_t, get_quote_info, bool, /* Secret assessment value 20 bytes (nonce) */ writer->write_data(writer, this->secret); - /* Length of the PCR selection field */ - writer->write_uint16(writer, size_of_select); - /* PCR selection */ - for (i = 0; i < size_of_select ; i++) - { - writer->write_uint8(writer, this->pcr_select[i]); - } + selection.ptr = pcr_comp.ptr; + selection.len = 2 + this->pcrs->get_selection_size(this->pcrs); + writer->write_data(writer, selection); /* TPM Locality Selection */ writer->write_uint8(writer, TPM_LOC_ZERO); @@ -1160,7 +1003,6 @@ METHOD(pts_t, get_quote_info, bool, writer->destroy(writer); free(pcr_comp.ptr); free(hash_pcr_comp.ptr); - clear_pcrs(this); return TRUE; } @@ -1192,7 +1034,7 @@ METHOD(pts_t, verify_quote_signature, bool, METHOD(pts_t, destroy, void, private_pts_t *this) { - clear_pcrs(this); + DESTROY_IF(this->pcrs); DESTROY_IF(this->aik); DESTROY_IF(this->dh); free(this->initiator_nonce.ptr); @@ -1374,6 +1216,14 @@ static bool has_tpm(private_pts_t *this) pts_t *pts_create(bool is_imc) { private_pts_t *this; + pts_pcr_t *pcrs; + + pcrs = pts_pcr_create(); + if (!pcrs) + { + DBG1(DBG_PTS, "shadow PCR set could not be created"); + return NULL; + } INIT(this, .public = { @@ -1391,7 +1241,6 @@ pts_t *pts_create(bool is_imc) .set_platform_info = _set_platform_info, .get_tpm_version_info = _get_tpm_version_info, .set_tpm_version_info = _set_tpm_version_info, - .get_pcr_len = _get_pcr_len, .get_aik = _get_aik, .set_aik = _set_aik, .get_aik_keyid = _get_aik_keyid, @@ -1400,8 +1249,7 @@ pts_t *pts_create(bool is_imc) .read_pcr = _read_pcr, .extend_pcr = _extend_pcr, .quote_tpm = _quote_tpm, - .select_pcr = _select_pcr, - .add_pcr = _add_pcr, + .get_pcrs = _get_pcrs, .get_quote_info = _get_quote_info, .verify_quote_signature = _verify_quote_signature, .destroy = _destroy, @@ -1410,6 +1258,7 @@ pts_t *pts_create(bool is_imc) .proto_caps = PTS_PROTO_CAPS_V, .algorithm = PTS_MEAS_ALGO_SHA256, .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256, + .pcrs = pcrs, ); if (is_imc) @@ -1419,7 +1268,6 @@ pts_t *pts_create(bool is_imc) if (has_tpm(this)) { this->has_tpm = TRUE; - this->pcr_len = PCR_LEN; this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D; load_aik(this); load_aik_blob(this); diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index c35f68687..5f88cd15c 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -29,6 +29,7 @@ typedef struct pts_t pts_t; #include "pts_file_meas.h" #include "pts_file_meta.h" #include "pts_dh_group.h" +#include "pts_pcr.h" #include "pts_req_func_comp_evid.h" #include "pts_simple_evid_final.h" #include "components/pts_comp_func_name.h" @@ -190,13 +191,6 @@ struct pts_t { void (*set_tpm_version_info)(pts_t *this, chunk_t info); /** - * Get the length of the TPM PCR registers - * - * @return Length of PCR registers in bytes, 0 if undefined - */ - size_t (*get_pcr_len)(pts_t *this); - - /** * Get Attestation Identity Certificate or Public Key * * @return AIK Certificate or Public Key @@ -273,24 +267,12 @@ struct pts_t { bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig); - /** - * Mark an extended PCR as selected - * - * @param pcr Number of the extended PCR - * @return TRUE if PCR number is valid - */ - bool (*select_pcr)(pts_t *this, u_int32_t pcr); - - /** - * Add an extended PCR with its corresponding value + /** + * Get the shadow PCR set * - * @param pcr Number of the extended PCR - * @param pcr_before PCR value before extension - * @param pcr_after PCR value after extension - * @return TRUE if PCR number and register length is valid + * @return shadow PCR set */ - bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before, - chunk_t pcr_after); + pts_pcr_t* (*get_pcrs)(pts_t *this); /** * Constructs and returns TPM Quote Info structure expected from IMC diff --git a/src/libpts/pts/pts_pcr.c b/src/libpts/pts/pts_pcr.c index c21e585e7..a7a2f5fae 100644 --- a/src/libpts/pts/pts_pcr.c +++ b/src/libpts/pts/pts_pcr.c @@ -17,15 +17,7 @@ #include <debug.h> -/** - * Maximum number of PCR's of TPM, TPM Spec 1.2 - */ -#define PCR_MAX_NUM 24 - -/** - * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2 - */ -#define PCR_LEN 20 +#include <stdarg.h> typedef struct private_pts_pcr_t private_pts_pcr_t; @@ -43,7 +35,22 @@ struct private_pts_pcr_t { /** * Shadow PCR registers */ - chunk_t pcrs[PCR_MAX_NUM]; + chunk_t pcrs[PTS_PCR_MAX_NUM]; + + /** + * Number of extended PCR registers + */ + u_int32_t pcr_count; + + /** + * Highest extended PCR register + */ + u_int32_t pcr_max; + + /** + * Bitmap of extended PCR registers + */ + u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8]; /** * Hasher used to extend shadow PCRs @@ -52,44 +59,186 @@ struct private_pts_pcr_t { }; +METHOD(pts_pcr_t, get_count, u_int32_t, + private_pts_pcr_t *this) +{ + return this->pcr_count; +} + +METHOD(pts_pcr_t, select_pcr, bool, + private_pts_pcr_t *this, u_int32_t pcr) +{ + u_int32_t i, f; + + if (pcr >= PTS_PCR_MAX_NUM) + { + DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u", + pcr, PTS_PCR_MAX_NUM-1); + return FALSE; + } + + /* Determine PCR selection flag */ + i = pcr / 8; + f = 1 << (pcr - 8*i); + + /* Has this PCR already been selected? */ + if (!(this->pcr_select[i] & f)) + { + this->pcr_select[i] |= f; + this->pcr_max = max(this->pcr_max, pcr); + this->pcr_count++; + } + return TRUE; +} + +METHOD(pts_pcr_t, get_selection_size, size_t, + private_pts_pcr_t *this) +{ + + /** + * A TPM v1.2 has 24 PCR Registers so the bitmask field length + * used by TrouSerS is at least 3 bytes + */ + return PTS_PCR_MAX_NUM / 8; +} + +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** current PCR */ + u_int32_t pcr; + /** back reference to parent */ + private_pts_pcr_t *pcrs; +} pcr_enumerator_t; + +/** + * Implementation of enumerator.enumerate + */ +static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...) +{ + u_int32_t *pcr, i, f; + va_list args; + + va_start(args, this); + pcr = va_arg(args, u_int32_t*); + va_end(args); + + while (this->pcr <= this->pcrs->pcr_max) + { + /* Determine PCR selection flag */ + i = this->pcr / 8; + f = 1 << (this->pcr - 8*i); + + /* Assign current PCR to output argument and increase */ + *pcr = this->pcr++; + + /* return if PCR is selected */ + if (this->pcrs->pcr_select[i] & f) + { + return TRUE; + } + } + return FALSE; +} + +METHOD(pts_pcr_t, create_enumerator, enumerator_t*, + private_pts_pcr_t *this) +{ + pcr_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)pcr_enumerator_enumerate, + .destroy = (void*)free, + }, + .pcrs = this, + ); + + return (enumerator_t*)enumerator; +} + METHOD(pts_pcr_t, get, chunk_t, private_pts_pcr_t *this, u_int32_t pcr) { - return (pcr < PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty; + return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty; } -METHOD(pts_pcr_t, set, void, +METHOD(pts_pcr_t, set, bool, private_pts_pcr_t *this, u_int32_t pcr, chunk_t value) { - if (pcr < PCR_MAX_NUM && value.len == PCR_LEN) + if (value.len != PTS_PCR_LEN) + { + DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr); + return FALSE; + } + if (select_pcr(this, pcr)) { - memcpy(this->pcrs[pcr].ptr, value.ptr, PCR_LEN); + memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN); + return TRUE; } + return FALSE; } METHOD(pts_pcr_t, extend, chunk_t, private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement) { - if (pcr >= PCR_MAX_NUM || measurement.len != PCR_LEN) + if (measurement.len != PTS_PCR_LEN) + { + DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr); + return chunk_empty; + } + if (!select_pcr(this, pcr)) { - DBG1(DBG_PTS, "PCR%d does not exist or has the wrong size", pcr); return chunk_empty; } if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) || !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr)) { - DBG1(DBG_PTS, "PCR%d was not extended due to a hasher problem", pcr); + DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr); return chunk_empty; } return this->pcrs[pcr]; } +METHOD(pts_pcr_t, get_composite, chunk_t, + private_pts_pcr_t *this) +{ + chunk_t composite; + enumerator_t *enumerator; + u_int16_t selection_size; + u_int32_t pcr_field_size, pcr; + u_char *pos; + + selection_size = get_selection_size(this); + pcr_field_size = this->pcr_count * PTS_PCR_LEN; + + composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size); + pos = composite.ptr; + htoun16(pos, selection_size); + pos += 2; + memcpy(pos, this->pcr_select, selection_size); + pos += selection_size; + htoun32(pos, pcr_field_size); + pos += 4; + + enumerator = create_enumerator(this); + while (enumerator->enumerate(enumerator, &pcr)) + { + memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN); + pos += PTS_PCR_LEN; + } + enumerator->destroy(enumerator); + + DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite); + return composite; +} + METHOD(pts_pcr_t, destroy, void, private_pts_pcr_t *this) { u_int32_t i; - for (i = 0; i < PCR_MAX_NUM; i++) + for (i = 0; i < PTS_PCR_MAX_NUM; i++) { free(this->pcrs[i].ptr); } @@ -116,18 +265,23 @@ pts_pcr_t *pts_pcr_create(void) INIT(this, .public = { + .get_count = _get_count, + .select_pcr = _select_pcr, + .get_selection_size = _get_selection_size, + .create_enumerator = _create_enumerator, .get = _get, .set = _set, .extend = _extend, + .get_composite = _get_composite, .destroy = _destroy, }, .hasher = hasher, ); - for (i = 0; i < PCR_MAX_NUM; i++) + for (i = 0; i < PTS_PCR_MAX_NUM; i++) { - this->pcrs[i] = chunk_alloc(PCR_LEN); - memset(this->pcrs[i].ptr, 0x00, PCR_LEN); + this->pcrs[i] = chunk_alloc(PTS_PCR_LEN); + memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN); } return &this->public; diff --git a/src/libpts/pts/pts_pcr.h b/src/libpts/pts/pts_pcr.h index 43a85dbe9..f638b5ee4 100644 --- a/src/libpts/pts/pts_pcr.h +++ b/src/libpts/pts/pts_pcr.h @@ -26,11 +26,50 @@ typedef struct pts_pcr_t pts_pcr_t; #include <library.h> /** + * Maximum number of PCR's of TPM, TPM Spec 1.2 + */ +#define PTS_PCR_MAX_NUM 24 + +/** + * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2 + */ +#define PTS_PCR_LEN 20 + +/** * Class implementing a shadow PCR register set */ struct pts_pcr_t { /** + * Get the number of selected PCRs + * + * @return number of selected PCRs + */ + u_int32_t (*get_count)(pts_pcr_t *this); + + /** + * Mark a PCR as selected + * + * @param pcr index of PCR + * @return TRUE if PCR index exists + */ + bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr); + + /** + * Get the size of the selection field in bytes + * + * @return number of bytes written + */ + size_t (*get_selection_size)(pts_pcr_t *this); + + /** + * Create an enumerator over all selected PCR indexes + * + * @return enumerator + */ + enumerator_t* (*create_enumerator)(pts_pcr_t *this); + + /** * Get the current content of a PCR * * @param pcr index of PCR @@ -43,8 +82,9 @@ struct pts_pcr_t { * * @param pcr index of PCR * @param value new value of PCR + * @return TRUE if value could be set */ - void (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value); + bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value); /** * Extend the content of a PCR @@ -56,6 +96,14 @@ struct pts_pcr_t { chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement); /** + * Create a PCR Composite object over all selected PCRs + * + * @return PCR Composite object (must be freed) + */ + chunk_t (*get_composite)(pts_pcr_t *this); + + /** + * Destroys a pts_pcr_t object. */ void (*destroy)(pts_pcr_t *this); |