sub-component depth from pts database on component evidence request
authorSansar Choinyambuu <schoinya@hsr.ch>
Wed, 23 Nov 2011 10:25:06 +0000 (11:25 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 28 Nov 2011 20:22:51 +0000 (21:22 +0100)
component hashes are entries in file_hashes table
implemented verify function of tboot component

13 files changed:
src/libimcv/plugins/imc_attestation/imc_attestation_process.c
src/libimcv/plugins/imv_attestation/data.sql
src/libimcv/plugins/imv_attestation/imv_attestation_build.c
src/libimcv/plugins/imv_attestation/tables.sql
src/libpts/pts/components/ita/ita_comp_tboot.c
src/libpts/pts/components/ita/ita_comp_tboot.h
src/libpts/pts/components/ita/ita_comp_tgrub.c
src/libpts/pts/components/ita/ita_comp_tgrub.h
src/libpts/pts/components/pts_component.h
src/libpts/pts/components/pts_component_manager.c
src/libpts/pts/components/pts_component_manager.h
src/libpts/pts/pts_database.c
src/libpts/pts/pts_database.h

index 34548f8..a93a950 100644 (file)
@@ -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");
index c6e09a0..ad5efb2 100644 (file)
@@ -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 (
@@ -309,6 +321,18 @@ INSERT INTO product_file (
 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 (
   5, 3
 );
 
@@ -402,30 +426,30 @@ INSERT INTO product_file (
   7, 22
 );
 
-/* Product Component */
-
-INSERT INTO product_component (
-  product, component, sequence
+INSERT INTO product_file (
+  product, file
 ) VALUES (
-  4, 1, 1
+  7, 23
 );
 
-INSERT INTO product_component (
-  product, component, sequence
+INSERT INTO product_file (
+  product, file
 ) VALUES (
-  4, 2, 2
+  7, 24
 );
 
+/* Product Component */
+
 INSERT INTO product_component (
-  product, component, sequence
+  product, component, depth, sequence
 ) VALUES (
-  7, 1, 1
+  4, 2, 0, 2
 );
 
 INSERT INTO product_component (
-  product, component, sequence
+  product, component, depth, 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'
 );
index 5d4f786..fb04ee0 100644 (file)
@@ -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);
 
index a8da57e..56616a0 100644 (file)
@@ -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)
-);
-
index 78c1efb..beb2a52 100644 (file)
@@ -41,6 +41,11 @@ struct pts_ita_comp_tboot_t {
        pts_comp_func_name_t *name;
 
        /**
+        * Sub-component depth
+        */
+       u_int32_t depth;
+
+       /**
         * Extended PCR last handled
         */
        u_int32_t extended_pcr;
@@ -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;
index f8945cb..8fba112 100644 (file)
@@ -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_ @}*/
index 08da860..d74451f 100644 (file)
@@ -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;
index 345c105..3c0ba02 100644 (file)
@@ -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_ @}*/
index 0950bed..42e592f 100644 (file)
@@ -50,6 +50,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
         *
         * @param pts                   PTS interface
index ddfeac8..5f11e41 100644 (file)
@@ -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;
                                }
                        }
index 05e7c12..c377949 100644 (file)
@@ -29,7 +29,8 @@ typedef struct pts_component_manager_t pts_component_manager_t;
 #include <library.h>
 #include <pen/pen.h>
 
-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.
index e72fb5a..b3089af 100644 (file)
@@ -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);
index 25bfa25..687c156 100644 (file)
@@ -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.