From 824a7824dcc20c0bec9750b9451019fc62f4ce27 Mon Sep 17 00:00:00 2001 From: Sansar Choinyambuu Date: Wed, 23 Nov 2011 11:25:06 +0100 Subject: [PATCH] sub-component depth from pts database on component evidence request component hashes are entries in file_hashes table implemented verify function of tboot component --- .../imc_attestation/imc_attestation_process.c | 2 +- src/libimcv/plugins/imv_attestation/data.sql | 68 +++++++++++++------ .../imv_attestation/imv_attestation_build.c | 8 ++- .../plugins/imv_attestation/tables.sql | 14 +--- .../pts/components/ita/ita_comp_tboot.c | 56 +++++++++++++-- .../pts/components/ita/ita_comp_tboot.h | 2 +- .../pts/components/ita/ita_comp_tgrub.c | 15 +++- .../pts/components/ita/ita_comp_tgrub.h | 2 +- src/libpts/pts/components/pts_component.h | 7 ++ .../pts/components/pts_component_manager.c | 5 +- .../pts/components/pts_component_manager.h | 6 +- src/libpts/pts/pts_database.c | 23 ++++--- src/libpts/pts/pts_database.h | 6 +- 13 files changed, 154 insertions(+), 60 deletions(-) diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c index 34548f867..a93a9509a 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c @@ -377,7 +377,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, "support sub component measurements"); return FALSE; } - comp = pts_components->create(pts_components, name); + comp = pts_components->create(pts_components, name, depth); if (!comp) { DBG2(DBG_IMC, " not registered: no evidence provided"); diff --git a/src/libimcv/plugins/imv_attestation/data.sql b/src/libimcv/plugins/imv_attestation/data.sql index c6e09a049..ad5efb2d2 100644 --- a/src/libimcv/plugins/imv_attestation/data.sql +++ b/src/libimcv/plugins/imv_attestation/data.sql @@ -176,6 +176,18 @@ INSERT INTO files ( 0, '/etc/tnc_config', 1 ); +INSERT INTO files ( + type, path +) VALUES ( + 0, 'tboot_pcr17' +); + +INSERT INTO files ( + type, path +) VALUES ( + 0, 'tboot_pcr18' +); + /* Components */ INSERT INTO components ( @@ -306,6 +318,18 @@ INSERT INTO product_file ( 4, 22 ); +INSERT INTO product_file ( + product, file +) VALUES ( + 4, 23 +); + +INSERT INTO product_file ( + product, file +) VALUES ( + 4, 24 +); + INSERT INTO product_file ( product, file ) VALUES ( @@ -402,30 +426,30 @@ INSERT INTO product_file ( 7, 22 ); +INSERT INTO product_file ( + product, file +) VALUES ( + 7, 23 +); + +INSERT INTO product_file ( + product, file +) VALUES ( + 7, 24 +); + /* Product Component */ INSERT INTO product_component ( - product, component, sequence + product, component, depth, sequence ) VALUES ( - 4, 1, 1 + 4, 2, 0, 2 ); INSERT INTO product_component ( - product, component, sequence + product, component, depth, sequence ) VALUES ( - 4, 2, 2 -); - -INSERT INTO product_component ( - product, component, sequence -) VALUES ( - 7, 1, 1 -); - -INSERT INTO product_component ( - product, component, sequence -) VALUES ( - 7, 2, 2 + 7, 2, 0, 2 ); /* File Hashes */ @@ -1295,14 +1319,14 @@ INSERT INTO file_hashes ( 20, 7, 7, 8192, X'84200bd318bb022915150842ddf4002e061ef593604ad0d07021dc662cc40bfa749cce084ddf25d0e5137f6380f613d8' ); -INSERT INTO component_hashes ( - component, product, algo, hash +INSERT INTO file_hashes ( + file, product, component, algo, hash ) VALUES ( - 2, 4, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902' + 23, 4, 2, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902' ); -INSERT INTO component_hashes ( - component, product, algo, hash +INSERT INTO file_hashes ( + file, product, component, algo, hash ) VALUES ( - 2, 4, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0' + 24, 4, 2, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0' ); diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_build.c b/src/libimcv/plugins/imv_attestation/imv_attestation_build.c index 5d4f78691..fb04ee036 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation_build.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation_build.c @@ -215,6 +215,7 @@ bool imv_attestation_build(pa_tnc_msg_t *msg, pts_comp_func_name_t *comp_name; int vid, name, qualifier; u_int8_t flags; + u_int32_t depth; bool first = TRUE; attestation_state->set_handshake_state(attestation_state, @@ -237,12 +238,13 @@ bool imv_attestation_build(pa_tnc_msg_t *msg, break; } DBG2(DBG_IMV, "evidence request by"); - while (enumerator->enumerate(enumerator, &vid, &name, &qualifier)) + while (enumerator->enumerate(enumerator, &vid, &name, + &qualifier, &depth)) { comp_name = pts_comp_func_name_create(vid, name, qualifier); comp_name->log(comp_name, " "); - comp = pts_components->create(pts_components, comp_name); + comp = pts_components->create(pts_components, comp_name, depth); if (!comp) { DBG2(DBG_IMV, " not registered: removed from request"); @@ -259,7 +261,7 @@ bool imv_attestation_build(pa_tnc_msg_t *msg, flags = comp->get_evidence_flags(comp); /* TODO check flags against negotiated_caps */ attr_cast = (tcg_pts_attr_req_func_comp_evid_t *)attr; - attr_cast->add_component(attr_cast, flags, 0, comp_name); + attr_cast->add_component(attr_cast, flags, depth, comp_name); } enumerator->destroy(enumerator); diff --git a/src/libimcv/plugins/imv_attestation/tables.sql b/src/libimcv/plugins/imv_attestation/tables.sql index a8da57ee6..56616a07d 100644 --- a/src/libimcv/plugins/imv_attestation/tables.sql +++ b/src/libimcv/plugins/imv_attestation/tables.sql @@ -38,6 +38,7 @@ DROP TABLE IF EXISTS product_component; CREATE TABLE product_component ( product INTEGER NOT NULL, component INTEGER NOT NULL, + depth INTEGER DEFAULT 0, sequence INTEGER DEFAULT 0, PRIMARY KEY (product, component) ); @@ -47,17 +48,8 @@ CREATE TABLE file_hashes ( file INTEGER NOT NULL, directory INTEGER DEFAULT 0, product INTEGER NOT NULL, + component INTEGER DEFAULT 0, algo INTEGER NOT NULL, hash BLOB NOT NULL, - PRIMARY KEY(file, directory, product, algo) + PRIMARY KEY(file, directory, product, component, algo) ); - -DROP TABLE IF EXISTS component_hashes; -CREATE TABLE component_hashes ( - component INTEGER NOT NULL, - product INTEGER NOT NULL, - algo INTEGER NOT NULL, - hash BLOB NOT NULL, - PRIMARY KEY(component, product, algo) -); - diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c index 78c1efb18..beb2a5283 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.c +++ b/src/libpts/pts/components/ita/ita_comp_tboot.c @@ -40,6 +40,11 @@ struct pts_ita_comp_tboot_t { */ pts_comp_func_name_t *name; + /** + * Sub-component depth + */ + u_int32_t depth; + /** * Extended PCR last handled */ @@ -64,6 +69,12 @@ METHOD(pts_component_t, get_evidence_flags, u_int8_t, return PTS_REQ_FUNC_COMP_EVID_PCR; } +METHOD(pts_component_t, get_depth, u_int32_t, + pts_ita_comp_tboot_t *this) +{ + return this->depth; +} + METHOD(pts_component_t, measure, status_t, pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence) { @@ -124,27 +135,62 @@ METHOD(pts_component_t, verify, status_t, pts_pcr_transform_t transform; time_t measurement_time; chunk_t measurement, pcr_before, pcr_after; + enumerator_t *enumerator; + char *file; + chunk_t hash; + char *platform_info; + + platform_info = pts->get_platform_info(pts); + if (!pts_db || !platform_info) + { + DBG1(DBG_PTS, "%s%s%s not available", + (pts_db) ? "" : "pts database", + (!pts_db && !platform_info) ? "and" : "", + (platform_info) ? "" : "platform info"); + return FAILED; + } switch (this->extended_pcr) { case 0: this->extended_pcr = PCR_TBOOT_POLICY; + file = "tboot_pcr17"; break; case PCR_TBOOT_POLICY: this->extended_pcr = PCR_TBOOT_MLE; + file = "tboot_pcr18"; break; default: return FAILED; } measurement = evidence->get_measurement(evidence, &extended_pcr, - &algo, &transform, &measurement_time); + &algo, &transform, &measurement_time); if (extended_pcr != this->extended_pcr) { return FAILED; } - /* TODO check measurement in database */ + /* check measurement in database */ + enumerator = pts_db->create_comp_hash_enumerator(pts_db, file, + platform_info, this->name, algo); + while (enumerator->enumerate(enumerator, &hash)) + { + if (!chunk_equals(hash, measurement)) + { + DBG1(DBG_PTS, "Incorrect TBOOT component measurement for PCR %d. " + "Expected: %#B, Received: %#B", + this->extended_pcr, &hash, &measurement); + return FAILED; + } + else + { + DBG3(DBG_PTS, "Matching TBOOT component measurement for PCR %d", + this->extended_pcr); + break; + } + } + enumerator->destroy(enumerator); has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); if (has_pcr_info) @@ -159,7 +205,7 @@ METHOD(pts_component_t, verify, status_t, } METHOD(pts_component_t, destroy, void, - pts_ita_comp_tboot_t *this) + pts_ita_comp_tboot_t *this) { this->name->destroy(this->name); free(this); @@ -168,7 +214,7 @@ METHOD(pts_component_t, destroy, void, /** * See header */ -pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier) +pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth) { pts_ita_comp_tboot_t *this; @@ -176,12 +222,14 @@ pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier) .public = { .get_comp_func_name = _get_comp_func_name, .get_evidence_flags = _get_evidence_flags, + .get_depth = _get_depth, .measure = _measure, .verify = _verify, .destroy = _destroy, }, .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT, qualifier), + .depth = depth, ); return &this->public; diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.h b/src/libpts/pts/components/ita/ita_comp_tboot.h index f8945cb5d..8fba1125a 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.h +++ b/src/libpts/pts/components/ita/ita_comp_tboot.h @@ -29,6 +29,6 @@ * @param qualifier PTS Component Functional Name Qualifier * */ -pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier); +pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth); #endif /** PTS_ITA_COMP_TBOOT_H_ @}*/ diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c index 08da86040..d74451fdf 100644 --- a/src/libpts/pts/components/ita/ita_comp_tgrub.c +++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c @@ -39,6 +39,11 @@ struct pts_ita_comp_tgrub_t { * Component Functional Name */ pts_comp_func_name_t *name; + + /** + * Sub-component depth + */ + u_int32_t depth; }; METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*, @@ -53,6 +58,12 @@ METHOD(pts_component_t, get_evidence_flags, u_int8_t, return PTS_REQ_FUNC_COMP_EVID_PCR; } +METHOD(pts_component_t, get_depth, u_int32_t, + pts_ita_comp_tgrub_t *this) +{ + return this->depth; +} + METHOD(pts_component_t, measure, status_t, pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence) { @@ -128,7 +139,7 @@ METHOD(pts_component_t, destroy, void, /** * See header */ -pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier) +pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth) { pts_ita_comp_tgrub_t *this; @@ -136,12 +147,14 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier) .public = { .get_comp_func_name = _get_comp_func_name, .get_evidence_flags = _get_evidence_flags, + .get_depth = _get_depth, .measure = _measure, .verify = _verify, .destroy = _destroy, }, .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT, qualifier), + .depth = depth, ); return &this->public; diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.h b/src/libpts/pts/components/ita/ita_comp_tgrub.h index 345c105c3..3c0ba0203 100644 --- a/src/libpts/pts/components/ita/ita_comp_tgrub.h +++ b/src/libpts/pts/components/ita/ita_comp_tgrub.h @@ -29,6 +29,6 @@ * @param qualifier PTS Component Functional Name Qualifier * */ -pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier); +pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth); #endif /** PTS_ITA_COMP_TGRUB_H_ @}*/ diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h index 0950beda8..42e592f3f 100644 --- a/src/libpts/pts/components/pts_component.h +++ b/src/libpts/pts/components/pts_component.h @@ -49,6 +49,13 @@ struct pts_component_t { */ u_int8_t (*get_evidence_flags)(pts_component_t *this); + /** + * Get the PTS Sub-component Depth + * + * @return PTS Sub-component Depth + */ + u_int32_t (*get_depth)(pts_component_t *this); + /** * Do evidence measurements on the PTS Functional Component * diff --git a/src/libpts/pts/components/pts_component_manager.c b/src/libpts/pts/components/pts_component_manager.c index ddfeac84a..5f11e41a7 100644 --- a/src/libpts/pts/components/pts_component_manager.c +++ b/src/libpts/pts/components/pts_component_manager.c @@ -252,7 +252,8 @@ METHOD(pts_component_manager_t, get_qualifier, u_int8_t, } METHOD(pts_component_manager_t, create, pts_component_t*, - private_pts_component_manager_t *this, pts_comp_func_name_t *name) + private_pts_component_manager_t *this, + pts_comp_func_name_t *name, u_int32_t depth) { enumerator_t *enumerator, *e2; vendor_entry_t *entry; @@ -269,7 +270,7 @@ METHOD(pts_component_manager_t, create, pts_component_t*, { if (entry2->name == name->get_name(name) && entry2->create) { - component = entry2->create(name->get_qualifier(name)); + component = entry2->create(name->get_qualifier(name), depth); break; } } diff --git a/src/libpts/pts/components/pts_component_manager.h b/src/libpts/pts/components/pts_component_manager.h index 05e7c12ea..c37794915 100644 --- a/src/libpts/pts/components/pts_component_manager.h +++ b/src/libpts/pts/components/pts_component_manager.h @@ -29,7 +29,8 @@ typedef struct pts_component_manager_t pts_component_manager_t; #include #include -typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier); +typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier, + u_int32_t depth); /** * Manages PTS Functional Components @@ -100,10 +101,11 @@ struct pts_component_manager_t { * Create a PTS Component object from a Functional Component Name object * * @param name Component Functional Name + * @param depth Sub-component Depth * @return Component object if supported, NULL else */ pts_component_t* (*create)(pts_component_manager_t *this, - pts_comp_func_name_t *name); + pts_comp_func_name_t *name, u_int32_t depth); /** * Destroys a pts_component_manager_t object. diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c index e72fb5ac2..b3089afcd 100644 --- a/src/libpts/pts/pts_database.c +++ b/src/libpts/pts/pts_database.c @@ -76,11 +76,12 @@ METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*, /* look for all entries belonging to a product in the components table */ e = this->db->query(this->db, - "SELECT c.vendor_id, c.name, c.qualifier FROM components AS c " + "SELECT c.vendor_id, c.name, c.qualifier, pc.depth " + "FROM components AS c " "JOIN product_component AS pc ON c.id = pc.component " "JOIN products AS p ON p.id = pc.product " "WHERE p.name = ? ORDER BY pc.sequence", - DB_TEXT, product, DB_INT, DB_INT, DB_INT); + DB_TEXT, product, DB_INT, DB_INT, DB_INT, DB_INT); return e; } @@ -114,18 +115,20 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*, } METHOD(pts_database_t, create_comp_hash_enumerator, enumerator_t*, - private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, - pts_comp_func_name_t *comp_name) + private_pts_database_t *this, char *file, char *product, + pts_comp_func_name_t *comp_name, pts_meas_algorithms_t algo) { enumerator_t *e; e = this->db->query(this->db, - "SELECT ch.hash FROM component_hashes AS ch " - "JOIN components AS c ON ch.component = c.id " - "JOIN products AS p ON ch.product = p.id " - "WHERE p.name = ? AND c.vendor_id = ? " - "AND c.name = ? AND c.qualifier = ? AND ch.algo = ? ", - DB_TEXT, product, DB_INT, comp_name->get_vendor_id(comp_name), + "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 " + "JOIN components AS c ON fh.component = c.id " + "WHERE f.path = ? AND p.name = ? AND c.vendor_id = ? " + "AND c.name = ? AND c.qualifier = ? AND fh.algo = ? ", + DB_TEXT, file, DB_TEXT, product, + DB_INT, comp_name->get_vendor_id(comp_name), DB_INT, comp_name->get_name(comp_name), DB_INT, comp_name->get_qualifier(comp_name), DB_INT, algo, DB_BLOB); diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h index 25bfa2539..687c156e2 100644 --- a/src/libpts/pts/pts_database.h +++ b/src/libpts/pts/pts_database.h @@ -76,14 +76,16 @@ struct pts_database_t { /** * Get stored measurement hash for functional component entries * + * @param file file path in files table * @param product software product (os, vpn client, etc.) * @param algo hash algorithm used for measurement * @param comp_name functional component name object * @return enumerator over all matching measurement hashes */ enumerator_t* (*create_comp_hash_enumerator)(pts_database_t *this, - char *product, pts_meas_algorithms_t algo, - pts_comp_func_name_t *comp_name); + char *file, char *product, + pts_comp_func_name_t *comp_name, + pts_meas_algorithms_t algo); /** * Destroys a pts_database_t object.