diff --git a/src/libpts/plugins/imv_attestation/imv_attestation.c b/src/libpts/plugins/imv_attestation/imv_attestation.c index 51069b02d..6aaf6a643 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation.c @@ -372,12 +372,6 @@ static TNC_Result receive_message(TNC_IMVID imv_id, attestation_state->get_file_meas_request_count(attestation_state)); attestation_state->set_measurement_error(attestation_state); } - if (attestation_state->get_component_count(attestation_state)) - { - DBG1(DBG_IMV, "failure due to %d components waiting for evidence", - attestation_state->get_component_count(attestation_state)); - attestation_state->set_measurement_error(attestation_state); - } if (attestation_state->get_measurement_error(attestation_state)) { state->set_recommendation(state, diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c index 21277a18c..96f663245 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c @@ -276,34 +276,21 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, pts_comp_evidence_t *evidence; pts_component_t *comp; u_int32_t depth; - status_t status; attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr; evidence = attr_cast->get_comp_evidence(attr_cast); name = evidence->get_comp_func_name(evidence, &depth); - comp = attestation_state->check_off_component(attestation_state, name); + comp = attestation_state->get_component(attestation_state, name); if (!comp) { DBG1(DBG_IMV, " no entry found for component evidence request"); break; } - status = comp->verify(comp, pts, evidence); - - switch (status) + if (comp->verify(comp, pts, evidence) != SUCCESS) { - default: - case FAILED: - attestation_state->set_measurement_error(attestation_state); - comp->destroy(comp); - break; - case SUCCESS: - name->log(name, " successfully measured "); - comp->destroy(comp); - break; - case NEED_MORE: - /* re-enter component into list */ - attestation_state->add_component(attestation_state, comp); + attestation_state->set_measurement_error(attestation_state); + name->log(name, " measurement mismatch for "); } break; } @@ -353,8 +340,11 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, DBG2(DBG_IMV, "TPM Quote Info signature verification successful"); free(quote_info.ptr); - /* Finalize any pending measurement registrations */ - attestation_state->check_off_registrations(attestation_state); + /** + * Finalize any pending measurement registrations and check + * if all expected component measurements were received + */ + attestation_state->finalize_components(attestation_state); } if (attr_cast->get_evid_sig(attr_cast, &evid_sig)) diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c index a58fd3ec3..7041bc514 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c @@ -296,7 +296,7 @@ METHOD(imv_attestation_state_t, add_component, void, this->components->insert_last(this->components, entry); } -METHOD(imv_attestation_state_t, check_off_component, pts_component_t*, +METHOD(imv_attestation_state_t, get_component, pts_component_t*, private_imv_attestation_state_t *this, pts_comp_func_name_t *name) { enumerator_t *enumerator; @@ -308,7 +308,6 @@ METHOD(imv_attestation_state_t, check_off_component, pts_component_t*, if (name->equals(name, entry->get_comp_func_name(entry))) { found = entry; - this->components->remove_at(this->components, enumerator); break; } } @@ -316,30 +315,6 @@ METHOD(imv_attestation_state_t, check_off_component, pts_component_t*, return found; } -METHOD(imv_attestation_state_t, check_off_registrations, void, - private_imv_attestation_state_t *this) -{ - enumerator_t *enumerator; - pts_component_t *entry; - - enumerator = this->components->create_enumerator(this->components); - while (enumerator->enumerate(enumerator, &entry)) - { - if (entry->check_off_registrations(entry)) - { - this->components->remove_at(this->components, enumerator); - entry->destroy(entry); - } - } - enumerator->destroy(enumerator); -} - -METHOD(imv_attestation_state_t, get_component_count, int, - private_imv_attestation_state_t *this) -{ - return this->components->get_count(this->components); -} - METHOD(imv_attestation_state_t, get_measurement_error, bool, private_imv_attestation_state_t *this) { @@ -352,6 +327,22 @@ METHOD(imv_attestation_state_t, set_measurement_error, void, this->measurement_error = TRUE; } +METHOD(imv_attestation_state_t, finalize_components, void, + private_imv_attestation_state_t *this) +{ + pts_component_t *entry; + + while (this->components->remove_last(this->components, + (void**)&entry) == SUCCESS) + { + if (!entry->finalize(entry)) + { + _set_measurement_error(this); + } + entry->destroy(entry); + } +} + /** * Described in header. */ @@ -380,9 +371,8 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) .check_off_file_meas_request = _check_off_file_meas_request, .get_file_meas_request_count = _get_file_meas_request_count, .add_component = _add_component, - .check_off_component = _check_off_component, - .check_off_registrations = _check_off_registrations, - .get_component_count = _get_component_count, + .get_component = _get_component, + .finalize_components = _finalize_components, .get_measurement_error = _get_measurement_error, .set_measurement_error = _set_measurement_error, }, diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h index 0e2c04da4..3e08f46a3 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h @@ -112,25 +112,19 @@ struct imv_attestation_state_t { void (*add_component)(imv_attestation_state_t *this, pts_component_t *entry); /** - * Returns the number of Functional Component waiting for evidence - * - * @return Number of waiting Functional Components - */ - int (*get_component_count)(imv_attestation_state_t *this); - - /** - * Check for presence of Functional Component and remove and return it + * Get a Functional Component with a given name * * @param name Name of the requested Functional Component * @return Functional Component if found, NULL otherwise */ - pts_component_t* (*check_off_component)(imv_attestation_state_t *this, - pts_comp_func_name_t *name); + pts_component_t* (*get_component)(imv_attestation_state_t *this, + pts_comp_func_name_t *name); /** * Tell the Functional Components to finalize any measurement registrations + * and to check if all expected measurements were received */ - void (*check_off_registrations)(imv_attestation_state_t *this); + void (*finalize_components)(imv_attestation_state_t *this); /** * Indicates if a file measurement error occurred diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c index a7da76651..e9c6b9dd0 100644 --- a/src/libpts/pts/components/ita/ita_comp_ima.c +++ b/src/libpts/pts/components/ita/ita_comp_ima.c @@ -29,11 +29,25 @@ #include #include -#define IMA_SECURITY_DIR "/sys/kernel/security/tpm0/" -#define IMA_BIOS_MEASUREMENT_PATH IMA_SECURITY_DIR "binary_bios_measurements" +#define SECURITY_DIR "/sys/kernel/security/" +#define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements" +#define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements" +#define IMA_PCR 10 #define IMA_PCR_MAX 16 +#define IMA_TYPE_LEN 3 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t; +typedef struct bios_entry_t bios_entry_t; +typedef struct ima_entry_t ima_entry_t; +typedef enum ima_state_t ima_state_t; + +enum ima_state_t { + IMA_STATE_INIT, + IMA_STATE_BIOS, + IMA_STATE_BIOS_AGGREGATE, + IMA_STATE_RUNTIME, + IMA_STATE_END +}; /** * Private data of a pts_ita_comp_ima_t object. @@ -81,38 +95,52 @@ struct pts_ita_comp_ima_t { */ bool is_registering; - /** - * IMA BIOS measurement time - */ - time_t bios_measurement_time; - - /** - * IMA BIOS measurements - */ - linked_list_t *list; - - /** - * Expected measurement count - */ - int count; - /** * Measurement sequence number */ int seq_no; + /** + * Expected IMA BIOS measurement count + */ + int count; + + /** + * IMA BIOS measurements + */ + linked_list_t *bios_list; + + /** + * IMA runtime file measurements + */ + linked_list_t *ima_list; + /** * Shadow PCR registers */ chunk_t pcrs[IMA_PCR_MAX]; + + /** + * IMA measurement time + */ + time_t measurement_time; + + /** + * IMA state machine + */ + ima_state_t state; + + /** + * Hasher used to extend emulated PCRs + */ + hasher_t *hasher; + }; -typedef struct entry_t entry_t; - /** - * Linux IMA measurement entry + * Linux IMA BIOS measurement entry */ -struct entry_t { +struct bios_entry_t { /** * PCR register @@ -126,21 +154,54 @@ struct entry_t { }; /** - * Free an entry_t object + * Linux IMA runtime file measurement entry */ -static void free_entry(entry_t *this) +struct ima_entry_t { + + /** + * SHA1 measurement hash + */ + chunk_t measurement; + + /** + * SHA1 file measurement thash + */ + chunk_t file_measurement; + + /** + * absolute path of executable files or basename of dynamic libraries + */ + chunk_t filename; +}; + +/** + * Free a bios_entry_t object + */ +static void free_bios_entry(bios_entry_t *this) { free(this->measurement.ptr); free(this); } +/** + * Free an ima_entry_t object + */ +static void free_ima_entry(ima_entry_t *this) +{ + free(this->measurement.ptr); + free(this->file_measurement.ptr); + free(this->filename.ptr); + free(this); +} + /** * Load a PCR measurement file and determine the creation date */ -static bool load_measurements(char *file, linked_list_t *list, time_t *created) +static bool load_bios_measurements(char *file, linked_list_t *list, + time_t *created) { u_int32_t pcr, num, len; - entry_t *entry; + bios_entry_t *entry; struct stat st; ssize_t res; int fd; @@ -148,13 +209,13 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created) fd = open(file, O_RDONLY); if (fd == -1) { - DBG1(DBG_PTS, " opening '%s' failed: %s", file, strerror(errno)); + DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno)); return FALSE; } if (fstat(fd, &st) == -1) { - DBG1(DBG_PTS, " getting statistics of '%s' failed: %s", file, + DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file, strerror(errno)); close(fd); return FALSE; @@ -167,12 +228,12 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created) if (res == 0) { DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)", - file, list->get_count(list)); + file, list->get_count(list)); close(fd); return TRUE; } - entry = malloc_thing(entry_t); + entry = malloc_thing(bios_entry_t); entry->pcr = pcr; entry->measurement = chunk_alloc(HASH_SIZE_SHA1); @@ -199,12 +260,123 @@ static bool load_measurements(char *file, linked_list_t *list, time_t *created) list->insert_last(list, entry); } - DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", - file, strerror(errno)); + DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file, + strerror(errno)); close(fd); return FALSE; } +/** + * Load an IMA runtime measurement file and determine the creation and + * update dates + */ +static bool load_runtime_measurements(char *file, linked_list_t *list, + time_t *created) +{ + u_int32_t pcr, len; + ima_entry_t *entry; + char type[IMA_TYPE_LEN]; + struct stat st; + ssize_t res; + int fd; + + fd = open(file, O_RDONLY); + if (fd == -1) + { + DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno)); + return TRUE; + } + + if (fstat(fd, &st) == -1) + { + DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file, + strerror(errno)); + close(fd); + return FALSE; + } + *created = st.st_ctime; + + while (TRUE) + { + res = read(fd, &pcr, 4); + if (res == 0) + { + DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)", + file, list->get_count(list)); + close(fd); + return TRUE; + } + + entry = malloc_thing(ima_entry_t); + entry->measurement = chunk_alloc(HASH_SIZE_SHA1); + entry->file_measurement = chunk_alloc(HASH_SIZE_SHA1); + entry->filename = chunk_empty; + + if (res != 4 || pcr != IMA_PCR) + { + break; + } + if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1) + { + break; + } + if (read(fd, &len, 4) != 4 || len != IMA_TYPE_LEN) + { + break; + } + if (read(fd, type, IMA_TYPE_LEN) != IMA_TYPE_LEN || + memcmp(type, "ima", IMA_TYPE_LEN)) + { + break; + } + if (read(fd, entry->file_measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1) + { + break; + } + if (read(fd, &len, 4) != 4) + { + break; + } + entry->filename = chunk_alloc(len); + if (read(fd, entry->filename.ptr, len) != len) + { + break; + } + list->insert_last(list, entry); + } + + DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s", + file, strerror(errno)); + close(fd); + return FALSE; +} + +/** + * Extend measurement into PCR an create evidence + */ +pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, + size_t pcr_len, chunk_t measurement) +{ + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; + pts_comp_evidence_t *evidence; + chunk_t pcr_before, pcr_after; + + hash_algo = PTS_MEAS_ALGO_SHA1; + pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); + pcr_before = chunk_clone(this->pcrs[pcr]); + this->hasher->get_hash(this->hasher, pcr_before, NULL); + this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr); + pcr_after = chunk_clone(this->pcrs[pcr]); + + evidence = pts_comp_evidence_create(this->name->clone(this->name), + this->depth, pcr, hash_algo, pcr_transform, + this->measurement_time, measurement); + evidence->set_pcr_info(evidence, pcr_before, pcr_after); + + return evidence; +} + METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*, pts_ita_comp_ima_t *this) { @@ -226,50 +398,78 @@ METHOD(pts_component_t, get_depth, u_int32_t, METHOD(pts_component_t, measure, status_t, pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t **evidence) { - pts_comp_evidence_t *evid; - chunk_t pcr_before, pcr_after; - pts_pcr_transform_t pcr_transform; - pts_meas_algorithms_t hash_algo; - size_t pcr_len; - entry_t *entry; - hasher_t *hasher; + bios_entry_t *bios_entry; + ima_entry_t *ima_entry; + status_t status; - hash_algo = PTS_MEAS_ALGO_SHA1; - pcr_len = pts->get_pcr_len(pts); - pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); - - if (this->list->get_count(this->list) == 0) + switch (this->state) { - if (!load_measurements(IMA_BIOS_MEASUREMENT_PATH, this->list, - &this->bios_measurement_time)) - { + case IMA_STATE_INIT: + if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS, this->bios_list, + &this->measurement_time)) + { + return FAILED; + } + this->state = IMA_STATE_BIOS; + /* fall through to next state */ + case IMA_STATE_BIOS: + status = this->bios_list->remove_first(this->bios_list, + (void**)&bios_entry); + if (status != SUCCESS) + { + DBG1(DBG_PTS, "could not retrieve bios measurement entry"); + return status; + } + *evidence = extend_pcr(this, bios_entry->pcr, pts->get_pcr_len(pts), + bios_entry->measurement); + free(bios_entry); + + /* break if still some BIOS measurements are left */ + if (this->bios_list->get_count(this->bios_list)) + { + break; + } + + /* check if IMA runtime measurements are enabled */ + if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS, + this->ima_list, &this->measurement_time)) + { + return FAILED; + } + + this->state = this->ima_list->get_count(this->ima_list) ? + IMA_STATE_BIOS_AGGREGATE : IMA_STATE_END; + break; + case IMA_STATE_BIOS_AGGREGATE: + case IMA_STATE_RUNTIME: + status = this->ima_list->remove_first(this->ima_list, + (void**)&ima_entry); + if (status != SUCCESS) + { + DBG1(DBG_PTS, "could not retrieve ima measurement entry"); + return status; + } + *evidence = extend_pcr(this, IMA_PCR, pts->get_pcr_len(pts), + ima_entry->measurement); + + /* TODO optionally send file measurements */ + chunk_free(&ima_entry->file_measurement); + chunk_free(&ima_entry->filename); + free(ima_entry); + + if (this->state == IMA_STATE_BIOS_AGGREGATE) + { + /* TODO check BIOS aggregate value */ + } + this->state = this->ima_list->get_count(this->ima_list) ? + IMA_STATE_RUNTIME : IMA_STATE_END; + break; + case IMA_STATE_END: + /* shouldn't happen */ return FAILED; - } } - if (this->list->remove_first(this->list, (void**)&entry) != SUCCESS) - { - DBG1(DBG_PTS, "could not retrieve measurement entry"); - return FAILED; - } - - pcr_before = chunk_clone(this->pcrs[entry->pcr]); - - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - hasher->get_hash(hasher, pcr_before, NULL); - hasher->get_hash(hasher, entry->measurement, this->pcrs[entry->pcr].ptr); - hasher->destroy(hasher); - - pcr_after = chunk_clone(this->pcrs[entry->pcr]); - - evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name), - this->depth, entry->pcr, hash_algo, pcr_transform, - this->bios_measurement_time, entry->measurement); - evid->set_pcr_info(evid, pcr_before, pcr_after); - - free(entry); - - return (this->list->get_count(this->list)) ? NEED_MORE : SUCCESS; + return (this->state == IMA_STATE_END) ? SUCCESS : NEED_MORE; } METHOD(pts_component_t, verify, status_t, @@ -282,6 +482,7 @@ METHOD(pts_component_t, verify, status_t, pts_pcr_transform_t transform; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; + status_t status; measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); @@ -299,11 +500,12 @@ METHOD(pts_component_t, verify, status_t, DBG1(DBG_PTS, "pts database not available"); return FAILED; } - if (this->pts_db->get_comp_measurement_count(this->pts_db, - this->name, this->keyid, algo, - &this->cid, &this->kid, &this->count) != SUCCESS) + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->keyid, algo, + &this->cid, &this->kid, &this->count); + if (status != SUCCESS) { - return FAILED; + return status; } vid = this->name->get_vendor_id(this->name); name = this->name->get_name(this->name); @@ -322,23 +524,28 @@ METHOD(pts_component_t, verify, status_t, } } - if (this->is_registering) + if (extended_pcr != IMA_PCR) { - if (this->pts_db->insert_comp_measurement(this->pts_db, measurement, - this->cid, this->kid, ++this->seq_no, - extended_pcr, algo) != SUCCESS) + if (this->is_registering) { - return FAILED; + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } + this->count = this->seq_no + 1; } - this->count = this->seq_no + 1; - } - else - { - if (this->pts_db->check_comp_measurement(this->pts_db, measurement, - this->cid, this->kid, ++this->seq_no, - extended_pcr, algo) != SUCCESS) + else { - return FAILED; + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } } } @@ -351,28 +558,35 @@ METHOD(pts_component_t, verify, status_t, } } - return (this->seq_no < this->count) ? NEED_MORE : SUCCESS; + return SUCCESS; } -METHOD(pts_component_t, check_off_registrations, bool, +METHOD(pts_component_t, finalize, bool, pts_ita_comp_ima_t *this) { u_int32_t vid, name; enum_name_t *names; - if (!this->is_registering) - { - return FALSE; - } - - /* Finalize registration */ - this->is_registering = FALSE; - vid = this->name->get_vendor_id(this->name); name = this->name->get_name(this->name); names = pts_components->get_comp_func_names(pts_components, vid); - DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence " - "measurements", this->seq_no, pen_names, vid, names, name); + + if (this->is_registering) + { + /* close registration */ + this->is_registering = FALSE; + + DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence " + "measurements", this->seq_no, pen_names, vid, names, name); + } + else if (this->seq_no < this->count) + { + DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence " + "measurements missing", this->count - this->seq_no, + this->count, pen_names, vid, names, name); + return FALSE; + } + return TRUE; } @@ -397,8 +611,10 @@ METHOD(pts_component_t, destroy, void, DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component " "evidence measurements", count, pen_names, vid, names, name); } - this->list->destroy_function(this->list, (void *)free_entry); + 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->hasher->destroy(this->hasher); free(this->keyid.ptr); free(this); } @@ -419,14 +635,16 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth, .get_depth = _get_depth, .measure = _measure, .verify = _verify, - .check_off_registrations = _check_off_registrations, + .finalize = _finalize, .destroy = _destroy, }, .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA, qualifier), .depth = depth, .pts_db = pts_db, - .list = linked_list_create(), + .bios_list = linked_list_create(), + .ima_list = linked_list_create(), + .hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1), ); for (i = 0; i < IMA_PCR_MAX; i++) diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c index a85de8cd8..dd26fdb96 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.c +++ b/src/libpts/pts/components/ita/ita_comp_tboot.c @@ -190,6 +190,7 @@ METHOD(pts_component_t, verify, status_t, pts_pcr_transform_t transform; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; + status_t status; measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); @@ -207,11 +208,12 @@ METHOD(pts_component_t, verify, status_t, DBG1(DBG_PTS, "pts database not available"); return FAILED; } - if (this->pts_db->get_comp_measurement_count(this->pts_db, - this->name, this->keyid, algo, - &this->cid, &this->kid, &this->count) != SUCCESS) + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->keyid, algo, &this->cid, + &this->kid, &this->count); + if (status != SUCCESS) { - return FAILED; + return status; } vid = this->name->get_vendor_id(this->name); name = this->name->get_name(this->name); @@ -232,21 +234,23 @@ METHOD(pts_component_t, verify, status_t, if (this->is_registering) { - if (this->pts_db->insert_comp_measurement(this->pts_db, measurement, - this->cid, this->kid, ++this->seq_no, - extended_pcr, algo) != SUCCESS) + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) { - return FAILED; + return status; } this->count = this->seq_no + 1; } else { - if (this->pts_db->check_comp_measurement(this->pts_db, measurement, - this->cid, this->kid, ++this->seq_no, - extended_pcr, algo) != SUCCESS) + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) { - return FAILED; + return status; } } @@ -259,28 +263,35 @@ METHOD(pts_component_t, verify, status_t, } } - return (this->seq_no < this->count) ? NEED_MORE : SUCCESS; + return SUCCESS; } -METHOD(pts_component_t, check_off_registrations, bool, +METHOD(pts_component_t, finalize, bool, pts_ita_comp_tboot_t *this) { u_int32_t vid, name; enum_name_t *names; - if (!this->is_registering) - { - return FALSE; - } - - /* Finalize registration */ - this->is_registering = FALSE; - vid = this->name->get_vendor_id(this->name); name = this->name->get_name(this->name); names = pts_components->get_comp_func_names(pts_components, vid); - DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence " - "measurements", this->seq_no, pen_names, vid, names, name); + + if (this->is_registering) + { + /* close registration */ + this->is_registering = FALSE; + + DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence " + "measurements", this->seq_no, pen_names, vid, names, name); + } + else if (this->seq_no < this->count) + { + DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence " + "measurements missing", this->count - this->seq_no, + this->count, pen_names, vid, names, name); + return FALSE; + } + return TRUE; } @@ -321,7 +332,7 @@ pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth, .get_depth = _get_depth, .measure = _measure, .verify = _verify, - .check_off_registrations = _check_off_registrations, + .finalize = _finalize, .destroy = _destroy, }, .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT, diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c index 0dfd5fd41..00b9ef3c5 100644 --- a/src/libpts/pts/components/ita/ita_comp_tgrub.c +++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c @@ -142,7 +142,7 @@ METHOD(pts_component_t, verify, status_t, return SUCCESS; } -METHOD(pts_component_t, check_off_registrations, bool, +METHOD(pts_component_t, finalize, bool, pts_ita_comp_tgrub_t *this) { return FALSE; @@ -170,7 +170,7 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth, .get_depth = _get_depth, .measure = _measure, .verify = _verify, - .check_off_registrations = _check_off_registrations, + .finalize = _finalize, .destroy = _destroy, }, .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB, diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h index 524ff332d..160fd0518 100644 --- a/src/libpts/pts/components/pts_component.h +++ b/src/libpts/pts/components/pts_component.h @@ -79,10 +79,11 @@ struct pts_component_t { /** * Tell the PTS Functional Component to finalize pending registrations + * and check for missing measurements * - * @return TRUE if there are pending registrations + * @return TRUE if finalization successful */ - bool (*check_off_registrations)(pts_component_t *this); + bool (*finalize)(pts_component_t *this); /** * Destroys a pts_component_t object. diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c index 282755c0a..bbada6183 100644 --- a/src/libpts/pts/pts_database.c +++ b/src/libpts/pts/pts_database.c @@ -169,7 +169,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t, "found in database", pcr, seq_no); DBG1(DBG_PTS, " expected: %#B", &hash); DBG1(DBG_PTS, " received: %#B", &measurement); - status = FAILED; + status = VERIFY_ERROR; break; } }