refactored PTS functional component measurements
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 5 Jul 2012 11:34:34 +0000 (13:34 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 11 Jul 2012 15:09:04 +0000 (17:09 +0200)
src/libpts/plugins/imv_attestation/imv_attestation.c
src/libpts/plugins/imv_attestation/imv_attestation_process.c
src/libpts/plugins/imv_attestation/imv_attestation_state.c
src/libpts/plugins/imv_attestation/imv_attestation_state.h
src/libpts/pts/components/ita/ita_comp_ima.c
src/libpts/pts/components/ita/ita_comp_tboot.c
src/libpts/pts/components/ita/ita_comp_tgrub.c
src/libpts/pts/components/pts_component.h
src/libpts/pts/pts_database.c

index 51069b0..6aaf6a6 100644 (file)
@@ -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,
index 21277a1..96f6632 100644 (file)
@@ -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))
index a58fd3e..7041bc5 100644 (file)
@@ -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,40 +315,32 @@ METHOD(imv_attestation_state_t, check_off_component, pts_component_t*,
        return found;
 }
 
-METHOD(imv_attestation_state_t, check_off_registrations, void,
+METHOD(imv_attestation_state_t, get_measurement_error, bool,
        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);
+       return this->measurement_error;
 }
 
-METHOD(imv_attestation_state_t, get_component_count, int,
+METHOD(imv_attestation_state_t, set_measurement_error, void,
        private_imv_attestation_state_t *this)
 {
-       return this->components->get_count(this->components);
+       this->measurement_error = TRUE;
 }
 
-METHOD(imv_attestation_state_t, get_measurement_error, bool,
+METHOD(imv_attestation_state_t, finalize_components, void,
        private_imv_attestation_state_t *this)
 {
-       return this->measurement_error;
-}
+       pts_component_t *entry;
 
-METHOD(imv_attestation_state_t, set_measurement_error, void,
-       private_imv_attestation_state_t *this)
-{
-       this->measurement_error = TRUE;
+       while (this->components->remove_last(this->components,
+                                                                               (void**)&entry) == SUCCESS)
+       {
+               if (!entry->finalize(entry))
+               {
+                       _set_measurement_error(this);
+               }
+               entry->destroy(entry);
+       }
 }
 
 /**
@@ -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,
                },
index 0e2c04d..3e08f46 100644 (file)
@@ -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
index a7da766..e9c6b9d 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 
-#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.
@@ -82,37 +96,51 @@ struct pts_ita_comp_ima_t {
        bool is_registering;
 
        /**
-     * IMA BIOS measurement time
+        * Measurement sequence number
         */
-       time_t bios_measurement_time;
+       int seq_no;
 
        /**
-     * IMA BIOS measurements
+        * Expected IMA BIOS measurement count
         */
-       linked_list_t *list;
+       int count;
 
        /**
-        * Expected measurement count
+     * IMA BIOS measurements
         */
-       int count;
+       linked_list_t *bios_list;
 
        /**
-        * Measurement sequence number
+     * IMA runtime file measurements
         */
-       int seq_no;
+       linked_list_t *ima_list;
 
        /**
         * Shadow PCR registers
         */
        chunk_t pcrs[IMA_PCR_MAX];
-};
 
-typedef struct entry_t entry_t;
+       /**
+        * IMA measurement time
+        */
+       time_t measurement_time;
+
+       /**
+        * IMA state machine
+        */
+       ima_state_t state;
+
+       /**
+        * Hasher used to extend emulated PCRs
+        */
+       hasher_t *hasher;
+
+};
 
 /**
- * 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
+ */
+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_entry(entry_t *this)
+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;
-
-       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);
+       bios_entry_t *bios_entry;
+       ima_entry_t *ima_entry;
+       status_t status;
 
-       if (this->list->get_count(this->list) == 0)
+       switch (this->state)
        {
-               if (!load_measurements(IMA_BIOS_MEASUREMENT_PATH, this->list,
-                                                          &this->bios_measurement_time))
-               {
-                       return FAILED;
-               }
-       }
+               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);
        
-       if (this->list->remove_first(this->list, (void**)&entry) != SUCCESS)
-       {
-               DBG1(DBG_PTS, "could not retrieve measurement entry");
-               return FAILED;
+                       /* 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;
        }
        
-       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)
+       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);
+
+       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;
        }
 
-       /* 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);
        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++)
index a85de8c..dd26fdb 100644 (file)
@@ -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)
+       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);
+
+       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;
        }
 
-       /* 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);
        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,
index 0dfd5fd..00b9ef3 100644 (file)
@@ -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,
index 524ff33..160fd05 100644 (file)
@@ -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.
index 282755c..bbada61 100644 (file)
@@ -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;
                }
        }