diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation.c b/src/libimcv/plugins/imv_attestation/imv_attestation.c index 4a87e875d..de93b9c30 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation.c @@ -488,13 +488,10 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, int file_count; pts_meas_algorithms_t algo; pts_file_meas_t *measurements; - chunk_t measurement; - char *platform_info, *filename; - enumerator_t *e_meas; + char *platform_info; + enumerator_t *e_hash; bool is_dir; - linked_list_t *files_in_dir_with_meas; - files_in_dir_with_meas = linked_list_create(); platform_info = pts->get_platform_info(pts); if (!pts_db || !platform_info) { @@ -516,51 +513,16 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id, DBG1(DBG_IMV, " no entry found for this request"); break; } - if (is_dir) + + /* check hashes from database against measurements */ + e_hash = pts_db->create_hash_enumerator(pts_db, + platform_info, algo, request_id, is_dir); + if (!measurements->verify(measurements, e_hash, is_dir)) { - enumerator_t *e; - char *file; - - e = pts_db->create_files_in_dir_enumerator(pts_db, request_id); - while (e->enumerate(e, &file)) - { - char *file_copy = (char *)malloc(strlen(file) * sizeof(char)); - strcpy(file_copy, file); - - files_in_dir_with_meas->insert_last(files_in_dir_with_meas, file_copy); - DBG3(DBG_IMV, "expecting measurement for: %s with request_id: %d", file_copy, request_id); - } - e->destroy(e); + DBG1(DBG_IMV, " measurement error occured"); + measurement_error = TRUE; } - - e_meas = measurements->create_enumerator(measurements); - while (e_meas->enumerate(e_meas, &filename, &measurement)) - { - bool hash_match; - - hash_match = pts_db->check_measurement(pts_db, measurement, - platform_info, request_id, filename, algo, is_dir); - - if (!hash_match) - { - measurement_error = TRUE; - } - - if (is_dir && files_in_dir_with_meas->remove(files_in_dir_with_meas, - filename, (bool (*)(void*,void*))string_equals)) - { - DBG3(DBG_IMV, "Removed %s from expected files list", filename); - } - } - - if (is_dir && - !files_in_dir_with_meas->get_count(files_in_dir_with_meas)) - { - DBG3(DBG_IMV, "recevied all expected file measurements for request: %d", request_id); - } - - files_in_dir_with_meas->destroy_function(files_in_dir_with_meas, free); - e_meas->destroy(e_meas); + e_hash->destroy(e_hash); break; } diff --git a/src/libimcv/tcg/pts/pts_database.c b/src/libimcv/tcg/pts/pts_database.c index f38e5dd10..594ddd0f7 100644 --- a/src/libimcv/tcg/pts/pts_database.c +++ b/src/libimcv/tcg/pts/pts_database.c @@ -54,68 +54,33 @@ METHOD(pts_database_t, create_file_enumerator, enumerator_t*, return e; } -METHOD(pts_database_t, create_files_in_dir_enumerator, enumerator_t*, - private_pts_database_t *this, int id) +METHOD(pts_database_t, create_hash_enumerator, enumerator_t*, + private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, + int id, bool is_dir) { enumerator_t *e; - /* look for all entries in file_hashes belonging to a same directory*/ - e = this->db->query(this->db, - "SELECT DISTINCT f.path FROM files AS f " - "JOIN file_hashes AS fh ON f.id = fh.file " - "WHERE fh.directory = ?", - DB_INT, id, DB_TEXT); + if (is_dir) + { + e = this->db->query(this->db, + "SELECT f.path, fh.hash FROM file_hashes AS fh " + "JOIN files AS f ON fh.file = f.id " + "JOIN products AS p ON fh.product = p.id " + "WHERE p.name = ? AND fh.directory = ? AND fh.algo = ?", + DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); + } + else + { + e = this->db->query(this->db, + "SELECT f.path, fh.hash FROM file_hashes AS fh " + "JOIN files AS f ON fh.file = f.id " + "JOIN products AS p ON fh.product = p.id " + "WHERE p.name = ? AND fh.file = ? AND fh.algo = ?", + DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); + } return e; } -METHOD(pts_database_t, check_measurement, bool, - private_pts_database_t *this, chunk_t received_hash, char *product, int id, char *file_name, pts_meas_algorithms_t algorithm, bool is_dir) -{ - enumerator_t *e; - chunk_t db_measurement; - - /* look for all entries belonging to a product, file and directory in file_hashes table */ - - e = (is_dir) ? this->db->query(this->db, - "SELECT fh.hash FROM file_hashes AS fh " - "JOIN files AS f ON fh.file = f.id " - "JOIN products AS p ON fh.product = p.id " - "WHERE f.path = ? AND p.name = ? AND fh.directory = ? AND fh.algo = ?", - DB_TEXT, file_name, DB_TEXT, product, DB_INT, id, DB_INT, algorithm, DB_BLOB) : - - this->db->query(this->db, - "SELECT fh.hash FROM file_hashes AS fh " - "JOIN files AS f ON fh.file = f.id " - "JOIN products AS p ON fh.product = p.id " - "WHERE p.name = ? AND f.id = ? AND fh.algo = ?", - DB_TEXT, product, DB_INT, id, DB_INT, algorithm, DB_BLOB); - - if (!e) - { - DBG1(DBG_TNC, " database enumerator failed"); - return FALSE; - } - if (!e->enumerate(e, &db_measurement)) - { - DBG2(DBG_TNC, " measurement for '%s' not found" - " in database", file_name); - e->destroy(e); - /* Ignore the measurements for which we do not have the hash saved in database */ - return TRUE; - } - if (chunk_equals(db_measurement, received_hash)) - { - DBG2(DBG_TNC, " %#B for '%s' is ok", - &received_hash, file_name); - return TRUE; - } - - DBG1(DBG_IMV, " %#B for '%s' does not match %#B", - &received_hash, file_name, &db_measurement); - return FALSE; -} - - METHOD(pts_database_t, destroy, void, private_pts_database_t *this) { @@ -133,8 +98,7 @@ pts_database_t *pts_database_create(char *uri) INIT(this, .public = { .create_file_enumerator = _create_file_enumerator, - .create_files_in_dir_enumerator = _create_files_in_dir_enumerator, - .check_measurement = _check_measurement, + .create_hash_enumerator = _create_hash_enumerator, .destroy = _destroy, }, .db = lib->db->create(lib->db, uri), diff --git a/src/libimcv/tcg/pts/pts_database.h b/src/libimcv/tcg/pts/pts_database.h index d69b0c1c4..f2a6854a5 100644 --- a/src/libimcv/tcg/pts/pts_database.h +++ b/src/libimcv/tcg/pts/pts_database.h @@ -35,33 +35,23 @@ struct pts_database_t { /** * Get files to be measured by PTS * - * @product software product (os, vpn client, etc.) - * @return enumerator over all files matching a given release + * @param product software product (os, vpn client, etc.) + * @return enumerator over all matching files */ enumerator_t* (*create_file_enumerator)(pts_database_t *this, char *product); /** - * Get Enumerator over files in a given directory with measurements + * Get stored measurement hash for single file or directory entries * - * @id primary key in files table, directory column in file_hashes table - * @return enumerator over all measurements matching a given release + * @param product software product (os, vpn client, etc.) + * @param algo hash algorithm used for measurement + * @param id primary key of measured file/directory + * @param is_dir TRUE if directory was measured + * @return enumerator over all matching measurement hashes */ - enumerator_t* (*create_files_in_dir_enumerator)(pts_database_t *this, int id); - - /** - * Get Hash measurement of a file in a folder with given id and hashing algorithm type - * - * @received_hash measurement of a file to match with database entry - * @product software product (os, vpn client, etc.) - * @id primary key in files table - * @file_name path in files table, obligatory for the files in directory - * @algorithm measurement algorithm type - * @is_dir TRUE if file is requested as content in a directory - * @return enumerator over all measurements matching a given release - */ - bool (*check_measurement)(pts_database_t *this, chunk_t received_hash, - char *product, int id, char *file_name, pts_meas_algorithms_t algorithm, bool is_dir); - + enumerator_t* (*create_hash_enumerator)(pts_database_t *this, char *product, + pts_meas_algorithms_t algo, + int id, bool is_dir); /** * Destroys a pts_database_t object. diff --git a/src/libimcv/tcg/pts/pts_file_meas.c b/src/libimcv/tcg/pts/pts_file_meas.c index 70bd5034d..82089499f 100644 --- a/src/libimcv/tcg/pts/pts_file_meas.c +++ b/src/libimcv/tcg/pts/pts_file_meas.c @@ -16,6 +16,7 @@ #include "pts_file_meas.h" #include +#include typedef struct private_pts_file_meas_t private_pts_file_meas_t; @@ -106,6 +107,52 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*, (void*)entry_filter, NULL, NULL); } +METHOD(pts_file_meas_t, verify, bool, + private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir) +{ + char *filename; + chunk_t measurement; + entry_t *entry; + enumerator_t *enumerator; + bool found, success = TRUE; + + while (e_hash->enumerate(e_hash, &filename, &measurement)) + { + found = FALSE; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (!is_dir || streq(filename, entry->filename)) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + DBG1(DBG_TNC, " no measurement found for '%s'", filename); + success = FALSE; + } + if (chunk_equals(measurement, entry->measurement)) + { + DBG2(DBG_TNC, " %#B for '%s' is ok", &measurement, filename); + } + else + { + DBG1(DBG_TNC, " %#B for '%s' is incorrect", &measurement, filename); + success = FALSE; + } + if (!is_dir) + { + break; + } + } + return success; +} + METHOD(pts_file_meas_t, destroy, void, private_pts_file_meas_t *this) { @@ -126,6 +173,7 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id) .get_file_count = _get_file_count, .add = _add, .create_enumerator = _create_enumerator, + .verify = _verify, .destroy = _destroy, }, .request_id = request_id, diff --git a/src/libimcv/tcg/pts/pts_file_meas.h b/src/libimcv/tcg/pts/pts_file_meas.h index fabd08b58..3ebb5c2a0 100644 --- a/src/libimcv/tcg/pts/pts_file_meas.h +++ b/src/libimcv/tcg/pts/pts_file_meas.h @@ -53,12 +53,21 @@ struct pts_file_meas_t { void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement); /** - * Create a PTS File Measurement enumerator - * - * @return Enumerator returning filename and measurement - */ + * Create a PTS File Measurement enumerator + * + * @return Enumerator returning filename and measurement + */ enumerator_t* (*create_enumerator)(pts_file_meas_t *this); + /** + * Verify stored hashes against PTS File Measurements + * + * @param e_hash Hash enumerator + * @paraem is_dir TRUE for directory contents hashes + * @return TRUE if all hashes match a measurement + */ + bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir); + /** * Destroys a pts_file_meas_t object. */