summaryrefslogtreecommitdiff
path: root/src/libpts/pts/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpts/pts/components')
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c807
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.h5
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c149
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.h5
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c65
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.h5
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.c22
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.h4
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.c9
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.h9
-rw-r--r--src/libpts/pts/components/pts_component.h24
-rw-r--r--src/libpts/pts/components/pts_component_manager.c6
-rw-r--r--src/libpts/pts/components/pts_component_manager.h3
13 files changed, 860 insertions, 253 deletions
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index a7da76651..a59732428 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +17,7 @@
#include "ita_comp_func_name.h"
#include "libpts.h"
+#include "pts/pts_pcr.h"
#include "pts/components/pts_component.h"
#include <debug.h>
@@ -29,11 +29,25 @@
#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 IMA_PCR_MAX 16
+#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_TYPE_LEN 3
+#define IMA_FILENAME_LEN_MAX 255
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_BOOT_AGGREGATE,
+ IMA_STATE_RUNTIME,
+ IMA_STATE_END
+};
/**
* Private data of a pts_ita_comp_ima_t object.
@@ -67,52 +81,101 @@ struct pts_ita_comp_ima_t {
pts_database_t *pts_db;
/**
- * Primary key for Component Functional Name database entry
+ * Primary key for AIK database entry
*/
- int cid;
+ int kid;
/**
- * Primary key for AIK database entry
+ * Primary key for IMA BIOS Component Functional Name database entry
*/
- int kid;
+ int bios_cid;
+
+ /**
+ * Primary key for IMA Runtime Component Functional Name database entry
+ */
+ int ima_cid;
/**
- * Component is registering measurements
+ * Component is registering IMA BIOS measurements
*/
- bool is_registering;
+ bool is_bios_registering;
+
+ /**
+ * Component is registering IMA boot aggregate measurement
+ */
+ bool is_ima_registering;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
/**
- * IMA BIOS measurement time
+ * Expected IMA BIOS measurement count
*/
- time_t bios_measurement_time;
+ int bios_count;
/**
* IMA BIOS measurements
*/
- linked_list_t *list;
+ linked_list_t *bios_list;
/**
- * Expected measurement count
+ * IMA runtime file measurements
+ */
+ linked_list_t *ima_list;
+
+ /**
+ * Whether to send pcr_before and pcr_after info
+ */
+ bool pcr_info;
+
+ /**
+ * IMA measurement time
+ */
+ time_t measurement_time;
+
+ /**
+ * IMA state machine
+ */
+ ima_state_t state;
+
+ /**
+ * Total number of component measurements
*/
int count;
/**
- * Measurement sequence number
+ * Number of successful component measurements
*/
- int seq_no;
+ int count_ok;
/**
- * Shadow PCR registers
+ * Number of unknown component measurements
*/
- chunk_t pcrs[IMA_PCR_MAX];
-};
+ int count_unknown;
-typedef struct entry_t entry_t;
+ /**
+ * Number of differing component measurements
+ */
+ int count_differ;
+
+ /**
+ * Number of failed component measurements
+ */
+ int count_failed;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
/**
- * Linux IMA measurement entry
+ * Linux IMA BIOS measurement entry
*/
-struct entry_t {
+struct bios_entry_t {
/**
* PCR register
@@ -126,21 +189,48 @@ struct entry_t {
};
/**
- * Free an entry_t object
+ * Linux IMA runtime file measurement entry
+ */
+struct ima_entry_t {
+
+ /**
+ * SHA1 measurement hash
+ */
+ chunk_t measurement;
+
+ /**
+ * absolute path of executable files or basename of dynamic libraries
+ */
+ char *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_entry(entry_t *this)
+static void free_ima_entry(ima_entry_t *this)
{
free(this->measurement.ptr);
+ free(this->filename);
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 +238,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 +257,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 +289,188 @@ 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->filename = NULL;
+
+ 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 (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
+ {
+ break;
+ }
+ if (read(fd, &len, 4) != 4)
+ {
+ break;
+ }
+ entry->filename = malloc(len + 1);
+ if (read(fd, entry->filename, len) != len)
+ {
+ break;
+ }
+ entry->filename[len] = '\0';
+
+ 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
+ */
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
+ u_int8_t qualifier, pts_pcr_t *pcrs,
+ u_int32_t pcr, chunk_t measurement)
+{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
+ pts_comp_func_name_t *name;
+ pts_comp_evidence_t *evidence;
+ chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
+
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ if (this->pcr_info)
+ {
+ pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
+ }
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (!pcr_after.ptr)
+ {
+ free(pcr_before.ptr);
+ return NULL;
+ }
+ name = this->name->clone(this->name);
+ name->set_qualifier(name, qualifier);
+ evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
+ pcr_transform, this->measurement_time, measurement);
+ if (this->pcr_info)
+ {
+ pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
+ evidence->set_pcr_info(evidence, pcr_before, pcr_after);
+ }
+ return evidence;
+}
+
+/**
+ * Compute and check boot aggregate value by hashing PCR0 to PCR7
+ */
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
+{
+ u_int32_t i;
+ u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+ u_char pcr_buffer[HASH_SIZE_SHA1];
+ chunk_t file_name, boot_aggregate;
+ hasher_t *hasher;
+ bool success, pcr_ok = TRUE;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, HASH_SHA1);
+ return FALSE;
+ }
+ for (i = 0; i < 8 && pcr_ok; i++)
+ {
+ pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
+ }
+ if (pcr_ok)
+ {
+ boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
+ memset(filename_buffer, 0, sizeof(filename_buffer));
+ strcpy(filename_buffer, "boot_aggregate");
+ file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+ pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer) &&
+ hasher->get_hash(hasher, boot_aggregate, NULL) &&
+ hasher->get_hash(hasher, file_name, boot_aggregate.ptr);
+ }
+ hasher->destroy(hasher);
+
+ if (pcr_ok)
+ {
+ success = chunk_equals(boot_aggregate, measurement);
+ DBG1(DBG_PTS, "boot aggregate value is %scorrect",
+ success ? "":"in");
+ return success;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "failed to compute boot aggregate value");
+ return FALSE;
+ }
+}
+
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
pts_ita_comp_ima_t *this)
{
@@ -224,193 +490,446 @@ 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_ita_comp_ima_t *this, u_int8_t qualifier, 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;
+ pts_pcr_t *pcrs;
+ pts_comp_evidence_t *evid = NULL;
+ 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);
+ pcrs = pts->get_pcrs(pts);
- if (this->list->get_count(this->list) == 0)
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- if (!load_measurements(IMA_BIOS_MEASUREMENT_PATH, this->list,
- &this->bios_measurement_time))
+ switch (this->state)
{
- return FAILED;
+ case IMA_STATE_INIT:
+ if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
+ this->bios_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->bios_count = this->bios_list->get_count(this->bios_list);
+ 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;
+ }
+ evid = extend_pcr(this, qualifier, pcrs, bios_entry->pcr,
+ bios_entry->measurement);
+ free(bios_entry);
+
+ this->state = this->bios_list->get_count(this->bios_list) ?
+ IMA_STATE_BIOS : IMA_STATE_INIT;
+ break;
+ default:
+ return FAILED;
}
}
-
- if (this->list->remove_first(this->list, (void**)&entry) != SUCCESS)
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ switch (this->state)
+ {
+ case IMA_STATE_INIT:
+ if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
+ this->ima_list, &this->measurement_time))
+ {
+ return FAILED;
+ }
+ this->state = IMA_STATE_BOOT_AGGREGATE;
+ /* fall through to next state */
+ case IMA_STATE_BOOT_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;
+ }
+ if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
+ {
+ if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+ {
+ return FAILED;
+ }
+ }
+ evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
+ ima_entry->measurement);
+ if (evid)
+ {
+ evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
+ ima_entry->filename);
+ }
+ free(ima_entry->filename);
+ free(ima_entry);
+
+ this->state = this->ima_list->get_count(this->ima_list) ?
+ IMA_STATE_RUNTIME : IMA_STATE_END;
+ break;
+ default:
+ return FAILED;
+ }
+ }
+ else
{
- DBG1(DBG_PTS, "could not retrieve measurement entry");
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
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);
+ *evidence = evid;
+ if (!evid)
+ {
+ return FAILED;
+ }
- return (this->list->get_count(this->list)) ? NEED_MORE : SUCCESS;
+ return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
+ SUCCESS : NEED_MORE;
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_ima_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
- u_int32_t extended_pcr, vid, name;
+ u_int32_t pcr, vid, name;
enum_name_t *names;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ status_t status;
+ char *uri;
- measurement = evidence->get_measurement(evidence, &extended_pcr,
- &algo, &transform, &measurement_time);
-
+ /* some first time initializations */
if (!this->keyid.ptr)
{
if (!pts->get_aik_keyid(pts, &this->keyid))
{
+ DBG1(DBG_PTS, "AIK keyid not available");
return FAILED;
}
this->keyid = chunk_clone(this->keyid);
-
if (!this->pts_db)
{
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)
- {
- return FAILED;
- }
- 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->count)
- {
- DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
- "measurements", this->count, pen_names, vid, names, name);
- }
- else
+ pcrs = pts->get_pcrs(pts);
+ measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
+ &measurement_time);
+
+ if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
+ {
+ switch (this->state)
{
- DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
- "measurements", pen_names, vid, names, name);
- this->is_registering = TRUE;
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo, &this->bios_cid,
+ &this->kid, &this->bios_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ 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->bios_count)
+ {
+ DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
+ this->bios_count, pen_names, vid, names, name);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
+ pen_names, vid, names, name);
+ this->is_bios_registering = TRUE;
+ }
+
+ this->state = IMA_STATE_BIOS;
+ /* fall through to next state */
+ case IMA_STATE_BIOS:
+ if (this->is_bios_registering)
+ {
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->bios_count = this->seq_no + 1;
+ }
+ else
+ {
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->bios_cid, this->kid,
+ ++this->seq_no, pcr, algo);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+ break;
+ default:
+ return FAILED;
}
}
-
- if (this->is_registering)
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
{
- if (this->pts_db->insert_comp_measurement(this->pts_db, measurement,
- this->cid, this->kid, ++this->seq_no,
- extended_pcr, algo) != SUCCESS)
+ int ima_count;
+
+ switch (this->state)
{
- return FAILED;
+ case IMA_STATE_BIOS:
+ if (!check_boot_aggregate(pcrs, measurement))
+ {
+ this->state = IMA_STATE_RUNTIME;
+ return FAILED;
+ }
+ this->state = IMA_STATE_INIT;
+ /* fall through to next state */
+ case IMA_STATE_INIT:
+ this->name->set_qualifier(this->name, qualifier);
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->keyid, algo,
+ &this->ima_cid, &this->kid, &ima_count);
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ 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 (ima_count)
+ {
+ DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ status = this->pts_db->check_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ this->is_ima_registering = TRUE;
+ status = this->pts_db->insert_comp_measurement(this->pts_db,
+ measurement, this->ima_cid,
+ this->kid, 1, pcr, algo);
+ }
+ this->state = IMA_STATE_RUNTIME;
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ break;
+ case IMA_STATE_RUNTIME:
+ this->count++;
+ if (evidence->get_validation(evidence, &uri) !=
+ PTS_COMP_EVID_VALIDATION_PASSED)
+ {
+ DBG1(DBG_PTS, "policy URI could no be retrieved");
+ this->count_failed++;
+ return FAILED;
+ }
+ status = this->pts_db->check_file_measurement(this->pts_db,
+ pts->get_platform_info(pts),
+ PTS_MEAS_ALGO_SHA1_IMA,
+ measurement, uri);
+ switch (status)
+ {
+ case SUCCESS:
+ DBG3(DBG_PTS, "%#B for '%s' is ok",
+ &measurement, uri);
+ this->count_ok++;
+ break;
+ case NOT_FOUND:
+ DBG2(DBG_PTS, "%#B for '%s' not found",
+ &measurement, uri);
+ this->count_unknown++;
+ break;
+ case VERIFY_ERROR:
+ DBG1(DBG_PTS, "%#B for '%s' differs",
+ &measurement, uri);
+ this->count_differ++;
+ break;
+ case FAILED:
+ default:
+ DBG1(DBG_PTS, "%#B for '%s' failed",
+ &measurement, uri);
+ this->count_failed++;
+ }
+ break;
+ default:
+ return FAILED;
}
- 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)
- {
- return FAILED;
- }
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ return FAILED;
}
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ pcr);
+ }
+ if (pcrs->set(pcrs, pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
-
- return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+ else
+ {
+ pcr_after = pcrs->extend(pcrs, pcr, measurement);
+ if (pcr_after.ptr)
+ {
+ return SUCCESS;
+ }
+ }
+ return FAILED;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_ima_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_ima_t *this, u_int8_t qualifier)
{
u_int32_t vid, name;
enum_name_t *names;
+ bool success = TRUE;
- if (!this->is_registering)
+ this->name->set_qualifier(this->name, qualifier);
+ 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 (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED))
{
- return FALSE;
+ /* finalize BIOS measurements */
+ if (this->is_bios_registering)
+ {
+ /* close registration */
+ this->is_bios_registering = FALSE;
+
+ DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
+ this->seq_no, pen_names, vid, names, name);
+ }
+ else if (this->seq_no < this->bios_count)
+ {
+ DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
+ this->bios_count - this->seq_no, this->bios_count,
+ pen_names, vid, names, name);
+ success = FALSE;
+ }
}
+ else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_OS))
+ {
+ /* finalize IMA file measurements */
+ if (this->is_ima_registering)
+ {
+ /* close registration */
+ this->is_ima_registering = FALSE;
- /* Finalize registration */
- this->is_registering = FALSE;
+ DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ if (this->count)
+ {
+ DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
+ "%d ok, %d unknown, %d differ, %d failed",
+ this->count, pen_names, vid, names, name,
+ this->count_ok, this->count_unknown,
+ this->count_differ, this->count_failed);
+ success = !this->count_differ && !this->count_failed;
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ success = FALSE;
+ }
+ this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
- 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;
+ return success;
+}
+
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_ima_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
}
METHOD(pts_component_t, destroy, void,
pts_ita_comp_ima_t *this)
{
- int i, count;
+ int count;
u_int32_t vid, name;
enum_name_t *names;
- for (i = 0; i < IMA_PCR_MAX; i++)
- {
- free(this->pcrs[i].ptr);
- }
- if (this->is_registering)
+ if (ref_put(&this->ref))
{
- count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
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, "deleted %d registered %N '%N' functional component "
- "evidence measurements", count, pen_names, vid, names, name);
+
+ if (this->is_bios_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->bios_cid, this->kid);
+ DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence "
+ "measurements", count, pen_names, vid, names, name);
+ }
+ if (this->is_ima_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->ima_cid, this->kid);
+ DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence "
+ "measurement", pen_names, vid, names, name);
+ }
+ 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);
+ free(this->keyid.ptr);
+ free(this);
}
- this->list->destroy_function(this->list, (void *)free_entry);
- this->name->destroy(this->name);
- free(this->keyid.ptr);
- free(this);
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_ima_t *this;
- int i;
INIT(this,
.public = {
@@ -419,21 +938,21 @@ 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,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
- qualifier),
+ PTS_QUALIFIER_UNKNOWN),
.depth = depth,
.pts_db = pts_db,
- .list = linked_list_create(),
+ .bios_list = linked_list_create(),
+ .ima_list = linked_list_create(),
+ .pcr_info = lib->settings->get_bool(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr_info", TRUE),
+ .ref = 1,
);
- for (i = 0; i < IMA_PCR_MAX; i++)
- {
- this->pcrs[i] = chunk_alloc(HASH_SIZE_SHA1);
- memset(this->pcrs[i].ptr, 0x00, HASH_SIZE_SHA1);
- }
return &this->public;
}
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.h b/src/libpts/pts/components/ita/ita_comp_ima.h
index 1ca27e6f0..546d0a4b2 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.h
+++ b/src/libpts/pts/components/ita/ita_comp_ima.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_ima_create(u_int32_t depth,
pts_database_t *pts_db);
#endif /** PTS_ITA_COMP_IMA_H_ @}*/
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index a85de8cd8..9deeb19b5 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -86,6 +85,11 @@ struct pts_ita_comp_tboot_t {
*/
int seq_no;
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
};
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
@@ -107,15 +111,18 @@ METHOD(pts_component_t, get_depth, u_int32_t,
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
+
{
+ size_t pcr_len;
+ pts_pcr_t *pcrs;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid;
char *meas_hex, *pcr_before_hex, *pcr_after_hex;
chunk_t measurement, pcr_before, pcr_after;
- size_t hash_size, pcr_len;
u_int32_t extended_pcr;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
switch (this->seq_no++)
{
@@ -149,9 +156,8 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
/* get and check the measurement data */
@@ -162,35 +168,40 @@ METHOD(pts_component_t, measure, status_t,
pcr_after = chunk_from_hex(
chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
- measurement.len != hash_size)
+ measurement.len != pcr_len)
{
- DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
+ DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
free(measurement.ptr);
free(pcr_before.ptr);
free(pcr_after.ptr);
return FAILED;
}
+ pcrs = pts->get_pcrs(pts);
+ pcrs->set(pcrs, extended_pcr, pcr_after);
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
- this->depth, extended_pcr,
- hash_algo, pcr_transform,
- this->measurement_time, measurement);
+ this->depth, extended_pcr, hash_algo, pcr_transform,
+ this->measurement_time, measurement);
evid->set_pcr_info(evid, pcr_before, pcr_after);
return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier,pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
u_int32_t extended_pcr, vid, name;
enum_name_t *names;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ status_t status;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
@@ -207,11 +218,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,58 +244,79 @@ 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;
}
}
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
+ extended_pcr);
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
- return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+ return SUCCESS;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_tboot_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier)
{
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;
}
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tboot_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
METHOD(pts_component_t, destroy, void,
pts_ita_comp_tboot_t *this)
{
@@ -291,25 +324,28 @@ METHOD(pts_component_t, destroy, void,
u_int32_t vid, name;
enum_name_t *names;
- if (this->is_registering)
+ if (ref_put(&this->ref))
{
- count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
- 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, "deleted %d registered %N '%N' functional component "
- "evidence measurements", count, pen_names, vid, names, name);
+ if (this->is_registering)
+ {
+ count = this->pts_db->delete_comp_measurements(this->pts_db,
+ this->cid, this->kid);
+ 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, "deleted %d registered %N '%N' functional component "
+ "evidence measurements", count, pen_names, vid, names, name);
+ }
+ this->name->destroy(this->name);
+ free(this->keyid.ptr);
+ free(this);
}
- this->name->destroy(this->name);
- free(this->keyid.ptr);
- free(this);
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_tboot_t *this;
@@ -321,13 +357,16 @@ 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,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
- qualifier),
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
.depth = depth,
.pts_db = pts_db,
+ .ref = 1,
);
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 39554fbc7..1e1a14831 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.h
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_tboot_create(u_int32_t depth,
pts_database_t *pts_db);
#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 0dfd5fd41..986f7ace2 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -50,6 +49,12 @@ struct pts_ita_comp_tgrub_t {
*/
pts_database_t *pts_db;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
};
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
@@ -71,15 +76,16 @@ METHOD(pts_component_t, get_depth, u_int32_t,
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t **evidence)
{
+ size_t pcr_len;
+ pts_pcr_transform_t pcr_transform;
+ pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid;
u_int32_t extended_pcr;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
- size_t hash_size, pcr_len;
/* Provisional implementation for TGRUB */
extended_pcr = PCR_DEBUG;
@@ -91,12 +97,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
- measurement = chunk_alloc(hash_size);
+ measurement = chunk_alloc(pcr_len);
memset(measurement.ptr, 0x00, measurement.len);
pcr_before = chunk_alloc(pcr_len);
@@ -112,15 +117,18 @@ METHOD(pts_component_t, measure, status_t,
}
METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t *evidence)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
{
bool has_pcr_info;
u_int32_t extended_pcr;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
if (extended_pcr != PCR_DEBUG)
@@ -133,32 +141,46 @@ METHOD(pts_component_t, verify, status_t,
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
{
- if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
+ if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{
- return FAILED;
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
+ {
+ return SUCCESS;
}
}
return SUCCESS;
}
-METHOD(pts_component_t, check_off_registrations, bool,
- pts_ita_comp_tgrub_t *this)
+METHOD(pts_component_t, finalize, bool,
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier)
{
return FALSE;
}
+METHOD(pts_component_t, get_ref, pts_component_t*,
+ pts_ita_comp_tgrub_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
METHOD(pts_component_t, destroy, void,
pts_ita_comp_tgrub_t *this)
{
- this->name->destroy(this->name);
- free(this);
+ if (ref_put(&this->ref))
+ {
+ this->name->destroy(this->name);
+ free(this);
+ }
}
/**
* See header
*/
-pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_tgrub_t *this;
@@ -170,13 +192,16 @@ 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,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB,
- qualifier),
+ PTS_ITA_QUALIFIER_FLAG_KERNEL |
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED),
.depth = depth,
.pts_db = pts_db,
+ .ref = 1,
);
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 52ecc325c..59913c82d 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.h
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,11 +26,10 @@
/**
* Create a PTS ITS Functional Component object
*
- * @param qualifier PTS Component Functional Name Qualifier
* @param depth Sub-component depth
* @param pts_db PTS measurement database
*/
-pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth,
+pts_component_t* pts_ita_comp_tgrub_create(u_int32_t depth,
pts_database_t *pts_db);
#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/
diff --git a/src/libpts/pts/components/pts_comp_evidence.c b/src/libpts/pts/components/pts_comp_evidence.c
index 9eb8dae75..050717472 100644
--- a/src/libpts/pts/components/pts_comp_evidence.c
+++ b/src/libpts/pts/components/pts_comp_evidence.c
@@ -87,7 +87,7 @@ struct private_pts_comp_evidence_t {
/**
* Verification Policy URI
*/
- chunk_t policy_uri;
+ char *policy_uri;
};
@@ -152,12 +152,12 @@ METHOD(pts_comp_evidence_t, set_pcr_info, void,
this->pcr_before = pcr_before;
this->pcr_after = pcr_after;
- DBG2(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
- DBG2(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
+ DBG3(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
+ DBG3(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
}
METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
- private_pts_comp_evidence_t *this, chunk_t *uri)
+ private_pts_comp_evidence_t *this, char **uri)
{
if (uri)
{
@@ -168,10 +168,14 @@ METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
METHOD(pts_comp_evidence_t, set_validation, void,
private_pts_comp_evidence_t *this, pts_comp_evid_validation_t validation,
- chunk_t uri)
+ char *uri)
{
this->validation = validation;
- this->policy_uri = chunk_clone(uri);
+ if (uri)
+ {
+ this->policy_uri = strdup(uri);
+ DBG3(DBG_PTS, "'%s'", uri);
+ }
}
METHOD(pts_comp_evidence_t, destroy, void,
@@ -181,7 +185,7 @@ METHOD(pts_comp_evidence_t, destroy, void,
free(this->measurement.ptr);
free(this->pcr_before.ptr);
free(this->pcr_after.ptr);
- free(this->policy_uri.ptr);
+ free(this->policy_uri);
free(this);
}
@@ -219,8 +223,8 @@ pts_comp_evidence_t *pts_comp_evidence_create(pts_comp_func_name_t *name,
);
name->log(name, "");
- DBG2(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
- DBG2(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
+ DBG3(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
+ DBG3(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
return &this->public;
}
diff --git a/src/libpts/pts/components/pts_comp_evidence.h b/src/libpts/pts/components/pts_comp_evidence.h
index fe86aa940..55776ce8b 100644
--- a/src/libpts/pts/components/pts_comp_evidence.h
+++ b/src/libpts/pts/components/pts_comp_evidence.h
@@ -120,7 +120,7 @@ struct pts_comp_evidence_t {
* @return validation Validation Result
*/
pts_comp_evid_validation_t (*get_validation)(pts_comp_evidence_t *this,
- chunk_t *uri);
+ char **uri);
/**
* Sets Validation Result if available
@@ -129,7 +129,7 @@ struct pts_comp_evidence_t {
* @param uri Verification Policy URI
*/
void (*set_validation)(pts_comp_evidence_t *this,
- pts_comp_evid_validation_t validation, chunk_t uri);
+ pts_comp_evid_validation_t validation, char* uri);
/**
* Destroys a pts_comp_evidence_t object.
diff --git a/src/libpts/pts/components/pts_comp_func_name.c b/src/libpts/pts/components/pts_comp_func_name.c
index d98850d78..7501be044 100644
--- a/src/libpts/pts/components/pts_comp_func_name.c
+++ b/src/libpts/pts/components/pts_comp_func_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
@@ -67,6 +67,12 @@ METHOD(pts_comp_func_name_t, get_qualifier, u_int8_t,
return this->qualifier;
}
+METHOD(pts_comp_func_name_t, set_qualifier, void,
+ private_pts_comp_func_name_t *this, u_int8_t qualifier)
+{
+ this->qualifier = qualifier;
+}
+
static bool equals(private_pts_comp_func_name_t *this,
private_pts_comp_func_name_t *other)
{
@@ -137,6 +143,7 @@ pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
.get_vendor_id = _get_vendor_id,
.get_name = _get_name,
.get_qualifier = _get_qualifier,
+ .set_qualifier = _set_qualifier,
.equals = (bool(*)(pts_comp_func_name_t*,pts_comp_func_name_t*))equals,
.clone = _clone_,
.log = _log_,
diff --git a/src/libpts/pts/components/pts_comp_func_name.h b/src/libpts/pts/components/pts_comp_func_name.h
index 2c7a84177..a3ffa1ba9 100644
--- a/src/libpts/pts/components/pts_comp_func_name.h
+++ b/src/libpts/pts/components/pts_comp_func_name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -55,6 +55,13 @@ struct pts_comp_func_name_t {
u_int8_t (*get_qualifier)(pts_comp_func_name_t *this);
/**
+ * Set the PTS Component Functional Name Qualifier
+ *
+ * @param qualifier PTS Component Functional Name Qualifier to be set
+ */
+ void (*set_qualifier)(pts_comp_func_name_t *this, u_int8_t qualifier);
+
+ /**
* Check to PTS Component Functional Names for equality
*
* @param other Other PTS Component Functional Name
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
index 524ff332d..da339a55f 100644
--- a/src/libpts/pts/components/pts_component.h
+++ b/src/libpts/pts/components/pts_component.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@ typedef struct pts_component_t pts_component_t;
#include "pts/pts.h"
#include "pts/pts_database.h"
+#include "pts/pts_file_meas.h"
#include "pts/components/pts_comp_func_name.h"
#include "pts/components/pts_comp_evidence.h"
@@ -59,30 +60,41 @@ struct pts_component_t {
/**
* Do evidence measurements on the PTS Functional Component
*
+ * @param qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence returns component evidence measureemt
+ * @param measurements additional file measurements (NULL if not present)
* @return status return code
*/
- status_t (*measure)(pts_component_t *this, pts_t *pts,
+ status_t (*measure)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t** evidence);
/**
* Verify the evidence measurements of the PTS Functional Component
*
+ * @param qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence component evidence measurement to be verified
* @return status return code
*/
- status_t (*verify)(pts_component_t *this, pts_t *pts,
+ status_t (*verify)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t *evidence);
-
/**
* Tell the PTS Functional Component to finalize pending registrations
+ * and check for missing measurements
+ *
+ * @param qualifier PTS Component Functional Name Qualifier
+ * @return TRUE if finalization successful
+ */
+ bool (*finalize)(pts_component_t *this, u_int8_t qualifier);
+
+ /**
+ * Get a new reference to the PTS Functional Component
*
- * @return TRUE if there are pending registrations
+ * @return this, with an increased refcount
*/
- bool (*check_off_registrations)(pts_component_t *this);
+ pts_component_t* (*get_ref)(pts_component_t *this);
/**
* Destroys a pts_component_t object.
diff --git a/src/libpts/pts/components/pts_component_manager.c b/src/libpts/pts/components/pts_component_manager.c
index 8ac4767bf..e330aeebf 100644
--- a/src/libpts/pts/components/pts_component_manager.c
+++ b/src/libpts/pts/components/pts_component_manager.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
- *
+ * Copyright (C) 2011-2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -270,8 +269,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),
- depth, pts_db);
+ component = entry2->create(depth, pts_db);
break;
}
}
diff --git a/src/libpts/pts/components/pts_component_manager.h b/src/libpts/pts/components/pts_component_manager.h
index 0079d0e26..61055ec74 100644
--- a/src/libpts/pts/components/pts_component_manager.h
+++ b/src/libpts/pts/components/pts_component_manager.h
@@ -30,8 +30,7 @@ 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,
- u_int32_t depth,
+typedef pts_component_t* (*pts_component_create_t)(u_int32_t depth,
pts_database_t *pts_db);
/**