summaryrefslogtreecommitdiff
path: root/src/libpts/pts/components
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
committerYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
commit81c63b0eed39432878f78727f60a1e7499645199 (patch)
tree82387d8fecd1c20788fd8bd784a9b0bde091fb6b /src/libpts/pts/components
parentc5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9 (diff)
downloadvyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.tar.gz
vyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.zip
Imported Upstream version 5.2.0
Diffstat (limited to 'src/libpts/pts/components')
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c694
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c95
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c7
-rw-r--r--src/libpts/pts/components/pts_component.h5
4 files changed, 372 insertions, 429 deletions
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index c6b4131bf..be8aa40ad 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,27 +18,20 @@
#include "libpts.h"
#include "pts/pts_pcr.h"
+#include "pts/pts_ima_bios_list.h"
+#include "pts/pts_ima_event_list.h"
#include "pts/components/pts_component.h"
#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
#include <pen/pen.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
#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
+#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 {
@@ -66,14 +59,9 @@ struct pts_ita_comp_ima_t {
pts_comp_func_name_t *name;
/**
- * AIK keyid
- */
- chunk_t keyid;
-
- /**
* Sub-component depth
*/
- u_int32_t depth;
+ uint32_t depth;
/**
* PTS measurement database
@@ -83,7 +71,7 @@ struct pts_ita_comp_ima_t {
/**
* Primary key for AIK database entry
*/
- int kid;
+ int aik_id;
/**
* Primary key for IMA BIOS Component Functional Name database entry
@@ -118,12 +106,12 @@ struct pts_ita_comp_ima_t {
/**
* IMA BIOS measurements
*/
- linked_list_t *bios_list;
+ pts_ima_bios_list_t *bios_list;
/**
* IMA runtime file measurements
*/
- linked_list_t *ima_list;
+ pts_ima_event_list_t *ima_list;
/**
* Whether to send pcr_before and pcr_after info
@@ -131,9 +119,9 @@ struct pts_ita_comp_ima_t {
bool pcr_info;
/**
- * IMA measurement time
+ * Creation time of measurement
*/
- time_t measurement_time;
+ time_t creation_time;
/**
* IMA state machine
@@ -173,222 +161,11 @@ struct pts_ita_comp_ima_t {
};
/**
- * Linux IMA BIOS measurement entry
- */
-struct bios_entry_t {
-
- /**
- * PCR register
- */
- u_int32_t pcr;
-
- /**
- * SHA1 measurement hash
- */
- chunk_t measurement;
-};
-
-/**
- * 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_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_bios_measurements(char *file, linked_list_t *list,
- time_t *created)
-{
- u_int32_t pcr, num, len;
- bios_entry_t *entry;
- 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 FALSE;
- }
-
- 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 bios measurements '%s' (%d entries)",
- file, list->get_count(list));
- close(fd);
- return TRUE;
- }
-
- entry = malloc_thing(bios_entry_t);
- entry->pcr = pcr;
- entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
-
- if (res != 4)
- {
- break;
- }
- if (read(fd, &num, 4) != 4)
- {
- break;
- }
- if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
- {
- break;
- }
- if (read(fd, &len, 4) != 4)
- {
- break;
- }
- if (lseek(fd, len, SEEK_CUR) == -1)
- {
- break;
- }
- list->insert_last(list, entry);
- }
-
- DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
- strerror(errno));
- free_bios_entry(entry);
- 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));
- free_ima_entry(entry);
- close(fd);
- return FALSE;
-}
-
-/**
- * Extend measurement into PCR an create evidence
+ * Extend measurement into PCR and 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)
+ uint8_t qualifier, pts_pcr_t *pcrs,
+ uint32_t pcr, chunk_t measurement)
{
size_t pcr_len;
pts_pcr_transform_t pcr_transform;
@@ -414,7 +191,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
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);
+ pcr_transform, this->creation_time, measurement);
if (this->pcr_info)
{
pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
@@ -424,15 +201,83 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
}
/**
+ * Generate an IMA or IMA-NG hash from an event digest and event name
+ *
+ * @param digest event digest
+ * @param ima_algo hash algorithm string ("sha1:", "sha256:", etc.)
+ * @param ima_name event name
+ * @param little_endian endianness of client platform
+ * @param algo hash algorithm used by TPM
+ * @param hash_buf hash value to be compared with TPM measurement
+ */
+static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
+ bool little_endian, pts_meas_algorithms_t algo,
+ char *hash_buf)
+{
+ hash_algorithm_t hash_alg;
+ hasher_t *hasher;
+ bool success;
+
+ hash_alg = pts_meas_algo_to_hash(algo);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "%N hasher could not be created",
+ hash_algorithm_short_names, hash_alg);
+ return FALSE;
+ }
+
+ if (ima_algo)
+ {
+ uint32_t d_len, n_len;
+ chunk_t algo_name, event_name, digest_len, name_len;
+
+ /* IMA-NG hash */
+ algo_name = chunk_create(ima_algo, strlen(ima_algo) + 1);
+ event_name = chunk_create(ima_name, strlen(ima_name) + 1);
+
+ d_len = algo_name.len + digest.len;
+ digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
+ /* TODO handle endianness of both client and server platforms */
+
+ n_len = event_name.len;
+ name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
+ /* TODO handle endianness of both client and server platforms */
+
+ success = hasher->get_hash(hasher, digest_len, NULL) &&
+ hasher->get_hash(hasher, algo_name, NULL) &&
+ hasher->get_hash(hasher, digest, NULL) &&
+ hasher->get_hash(hasher, name_len, NULL) &&
+ hasher->get_hash(hasher, event_name, hash_buf);
+ }
+ else
+ {
+ u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+ chunk_t file_name;
+
+ /* IMA legacy hash */
+ memset(filename_buffer, 0, sizeof(filename_buffer));
+ strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
+ file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+ success = hasher->get_hash(hasher, digest, NULL) &&
+ hasher->get_hash(hasher, file_name, hash_buf);
+ }
+ hasher->destroy(hasher);
+
+ return success;
+}
+
+/**
* Compute and check boot aggregate value by hashing PCR0 to PCR7
*/
-static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
+ char *algo)
{
- 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;
+ chunk_t boot_aggregate;
hasher_t *hasher;
+ uint32_t i;
bool success, pcr_ok = TRUE;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
@@ -448,19 +293,20 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
}
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);
+ pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
}
hasher->destroy(hasher);
if (pcr_ok)
{
+ boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
+
+ /* TODO handle endianness of client platform */
+ pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
+ TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
+ }
+ if (pcr_ok)
+ {
success = chunk_equals(boot_aggregate, measurement);
DBG1(DBG_PTS, "boot aggregate value is %scorrect",
success ? "":"in");
@@ -479,26 +325,28 @@ METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
return this->name;
}
-METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+METHOD(pts_component_t, get_evidence_flags, uint8_t,
pts_ita_comp_ima_t *this)
{
return PTS_REQ_FUNC_COMP_EVID_PCR;
}
-METHOD(pts_component_t, get_depth, u_int32_t,
+METHOD(pts_component_t, get_depth, uint32_t,
pts_ita_comp_ima_t *this)
{
return this->depth;
}
METHOD(pts_component_t, measure, status_t,
- pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
pts_comp_evidence_t **evidence)
{
- bios_entry_t *bios_entry;
- ima_entry_t *ima_entry;
pts_pcr_t *pcrs;
pts_comp_evidence_t *evid = NULL;
+ size_t algo_len, name_len;
+ chunk_t measurement;
+ char *uri, *algo, *name;
+ uint32_t pcr;
status_t status;
pcrs = pts->get_pcrs(pts);
@@ -509,25 +357,25 @@ METHOD(pts_component_t, measure, status_t,
switch (this->state)
{
case IMA_STATE_INIT:
- if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
- this->bios_list, &this->measurement_time))
+ this->bios_list = pts_ima_bios_list_create(
+ IMA_BIOS_MEASUREMENTS);
+ if (!this->bios_list)
{
return FAILED;
}
+ this->creation_time = this->bios_list->get_time(this->bios_list);
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);
+ status = this->bios_list->get_next(this->bios_list, &pcr,
+ &measurement);
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);
+ evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
this->state = this->bios_list->get_count(this->bios_list) ?
IMA_STATE_BIOS : IMA_STATE_INIT;
@@ -542,17 +390,20 @@ METHOD(pts_component_t, measure, status_t,
switch (this->state)
{
case IMA_STATE_INIT:
- if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
- this->ima_list, &this->measurement_time))
+ this->ima_list = pts_ima_event_list_create(
+ IMA_RUNTIME_MEASUREMENTS);
+ if (!this->ima_list)
{
return FAILED;
}
+ this->creation_time = this->ima_list->get_time(this->ima_list);
+ this->count = this->ima_list->get_count(this->ima_list);
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);
+ status = this->ima_list->get_next(this->ima_list, &measurement,
+ &algo, &name);
if (status != SUCCESS)
{
DBG1(DBG_PTS, "could not retrieve ima measurement entry");
@@ -560,20 +411,33 @@ METHOD(pts_component_t, measure, status_t,
}
if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
{
- if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+ if (!check_boot_aggregate(pcrs, measurement, algo))
{
return FAILED;
}
}
evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
- ima_entry->measurement);
+ measurement);
if (evid)
{
+ if (algo)
+ {
+ algo_len = strlen(algo);
+ name_len = strlen(name);
+ uri = malloc(algo_len + name_len + 1);
+ memcpy(uri, algo, algo_len);
+ strcpy(uri + algo_len, name);
+ }
+ else
+ {
+ uri = strdup(name);
+ }
evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
- ima_entry->filename);
+ uri);
+ free(uri);
}
- free(ima_entry->filename);
- free(ima_entry);
+ free(name);
+ free(algo);
this->state = this->ima_list->get_count(this->ima_list) ?
IMA_STATE_RUNTIME : IMA_STATE_END;
@@ -598,40 +462,80 @@ METHOD(pts_component_t, measure, status_t,
SUCCESS : NEED_MORE;
}
-METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
- pts_comp_evidence_t *evidence)
+/**
+ * Parse a validation URI of the form <hash algorithm>:<event name>
+ * into its components
+ */
+static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
+ char **ima_name, char **ima_algo, char *algo_buf)
{
- bool has_pcr_info;
- 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;
+ pts_meas_algorithms_t hash_algo;
+ char *uri, *pos, *algo, *name;
- /* some first time initializations */
- if (!this->keyid.ptr)
+ evidence->get_validation(evidence, &uri);
+
+ /* IMA-NG format? */
+ pos = strchr(uri, ':');
+ if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
{
- if (!pts->get_aik_keyid(pts, &this->keyid))
+ memset(algo_buf, '\0', IMA_ALGO_LEN_MAX);
+ memcpy(algo_buf, uri, pos - uri + 1);
+ algo = algo_buf;
+ name = pos + 1;
+
+ if (streq(algo, "sha1:") || streq(algo, ":"))
+ {
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ }
+ else if (streq(algo, "sha256:"))
{
- DBG1(DBG_PTS, "AIK keyid not available");
- return FAILED;
+ hash_algo = PTS_MEAS_ALGO_SHA256;
}
- this->keyid = chunk_clone(this->keyid);
- if (!this->pts_db)
+ else if (streq(algo, "sha384:"))
{
- DBG1(DBG_PTS, "pts database not available");
- return FAILED;
+ hash_algo = PTS_MEAS_ALGO_SHA384;
+ }
+ else
+ {
+ hash_algo = PTS_MEAS_ALGO_NONE;
}
}
+ else
+ {
+ algo = NULL;
+ name = uri;
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ }
+
+ if (ima_name)
+ {
+ *ima_name = name;
+ }
+ if (ima_algo)
+ {
+ *ima_algo = algo;
+ }
+
+ return hash_algo;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
+ pts_comp_evidence_t *evidence)
+{
+ bool has_pcr_info;
+ uint32_t pcr;
+ pts_meas_algorithms_t algo;
+ pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
+ time_t creation_time;
+ chunk_t measurement, pcr_before, pcr_after;
+ status_t status = NOT_FOUND;
+ this->aik_id = pts->get_aik_id(pts);
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
- &measurement_time);
+ &creation_time);
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -641,26 +545,22 @@ METHOD(pts_component_t, verify, status_t,
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, this->aik_id, algo,
+ &this->bios_cid, &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);
+ DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
+ this->bios_count);
}
else
{
- DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
- pen_names, vid, names, name);
+ DBG1(DBG_PTS, "registering BIOS evidence measurements");
this->is_bios_registering = TRUE;
}
@@ -670,8 +570,8 @@ METHOD(pts_component_t, verify, status_t,
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);
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
if (status != SUCCESS)
{
return status;
@@ -681,8 +581,8 @@ METHOD(pts_component_t, verify, status_t,
else
{
status = this->pts_db->check_comp_measurement(this->pts_db,
- measurement, this->bios_cid, this->kid,
- ++this->seq_no, pcr, algo);
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
if (status == FAILED)
{
return status;
@@ -697,13 +597,34 @@ METHOD(pts_component_t, verify, status_t,
PTS_ITA_QUALIFIER_TYPE_OS))
{
int ima_count;
+ char *ima_algo, *ima_name;
+ char algo_buf[IMA_ALGO_LEN_MAX];
+ pts_meas_algorithms_t hash_algo;
+
+ hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
+ algo_buf);
switch (this->state)
{
case IMA_STATE_BIOS:
- if (!check_boot_aggregate(pcrs, measurement))
+ this->state = IMA_STATE_RUNTIME;
+
+ if (!streq(ima_name, "boot_aggregate"))
+ {
+ DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' "
+ "but is '%s'", ima_name);
+ return FAILED;
+ }
+ if (hash_algo != PTS_MEAS_ALGO_SHA1)
+ {
+ DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
+ "but is %N",
+ pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
+ pts_meas_algorithm_names, hash_algo);
+ return FAILED;
+ }
+ if (!check_boot_aggregate(pcrs, measurement, ima_algo))
{
- this->state = IMA_STATE_RUNTIME;
return FAILED;
}
this->state = IMA_STATE_INIT;
@@ -711,33 +632,30 @@ METHOD(pts_component_t, verify, status_t,
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, this->aik_id, algo,
+ &this->ima_cid, &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);
+ DBG1(DBG_PTS, "checking boot aggregate evidence "
+ "measurement");
status = this->pts_db->check_comp_measurement(this->pts_db,
measurement, this->ima_cid,
- this->kid, 1, pcr, algo);
+ this->aik_id, 1, pcr, algo);
}
else
{
- DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ DBG1(DBG_PTS, "registering boot aggregate evidence "
+ "measurement");
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->aik_id, 1, pcr, algo);
}
this->state = IMA_STATE_RUNTIME;
@@ -747,42 +665,76 @@ METHOD(pts_component_t, verify, status_t,
}
break;
case IMA_STATE_RUNTIME:
+ {
+ uint8_t hash_buf[HASH_SIZE_SHA512];
+ chunk_t digest, hash;
+ enumerator_t *e;
+
this->count++;
- if (evidence->get_validation(evidence, &uri) !=
+ if (evidence->get_validation(evidence, NULL) !=
PTS_COMP_EVID_VALIDATION_PASSED)
{
- DBG1(DBG_PTS, "policy URI could no be retrieved");
+ DBG1(DBG_PTS, "evidence validation failed");
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);
+ hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
+
+ e = this->pts_db->create_file_meas_enumerator(this->pts_db,
+ pts->get_platform_id(pts),
+ hash_algo, ima_name);
+ if (e)
+ {
+ while (e->enumerate(e, &digest))
+ {
+ if (!ima_hash(digest, ima_algo, ima_name,
+ FALSE, algo, hash_buf))
+ {
+ status = FAILED;
+ break;
+ }
+ if (chunk_equals(measurement, hash))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ status = VERIFY_ERROR;
+ }
+ }
+ e->destroy(e);
+ }
+ else
+ {
+ status = FAILED;
+ }
+
switch (status)
{
case SUCCESS:
DBG3(DBG_PTS, "%#B for '%s' is ok",
- &measurement, uri);
+ &measurement, ima_name);
this->count_ok++;
break;
case NOT_FOUND:
DBG2(DBG_PTS, "%#B for '%s' not found",
- &measurement, uri);
+ &measurement, ima_name);
this->count_unknown++;
break;
case VERIFY_ERROR:
DBG1(DBG_PTS, "%#B for '%s' differs",
- &measurement, uri);
+ &measurement, ima_name);
this->count_differ++;
break;
case FAILED:
default:
DBG1(DBG_PTS, "%#B for '%s' failed",
- &measurement, uri);
+ &measurement, ima_name);
this->count_failed++;
}
break;
+ }
default:
return FAILED;
}
@@ -818,16 +770,15 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_ima_t *this, u_int8_t qualifier)
+ pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
{
- u_int32_t vid, name;
- enum_name_t *names;
+ char result_buf[BUF_LEN];
+ char *pos = result_buf;
+ size_t len = BUF_LEN;
+ int written;
bool success = TRUE;
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))
@@ -838,16 +789,20 @@ METHOD(pts_component_t, finalize, bool,
/* 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);
+ snprintf(pos, len, "registered %d BIOS evidence measurements",
+ this->seq_no);
}
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);
+ snprintf(pos, len, "%d of %d BIOS evidence measurements missing",
+ this->bios_count - this->seq_no, this->bios_count);
success = FALSE;
}
+ else
+ {
+ snprintf(pos, len, "%d BIOS evidence measurements are ok",
+ this->bios_count);
+ }
}
else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
PTS_ITA_QUALIFIER_TYPE_OS))
@@ -858,26 +813,34 @@ METHOD(pts_component_t, finalize, bool,
/* close registration */
this->is_ima_registering = FALSE;
- DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ written = snprintf(pos, len, "registered IMA boot aggregate "
+ "evidence measurement; ");
+ pos += written;
+ len -= written;
}
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;
+ snprintf(pos, len, "processed %d IMA file evidence measurements: "
+ "%d ok, %d unknown, %d differ, %d failed",
+ this->count, this->count_ok, this->count_unknown,
+ this->count_differ, this->count_failed);
+ }
+ else
+ {
+ snprintf(pos, len, "no IMA file evidence measurements");
+ success = FALSE;
}
}
else
{
- DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ snprintf(pos, len, "unsupported functional component name qualifier");
success = FALSE;
}
this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
+ DBG1(DBG_PTS, "%s", result_buf);
+ result->write_data(result, chunk_from_str(result_buf));
+
return success;
}
@@ -892,35 +855,28 @@ METHOD(pts_component_t, destroy, void,
pts_ita_comp_ima_t *this)
{
int count;
- u_int32_t vid, name;
- enum_name_t *names;
if (ref_put(&this->ref))
{
- 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_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);
+ this->bios_cid, this->aik_id);
+ DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements",
+ count);
}
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->ima_cid, this->aik_id);
+ DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
+ "measurement");
}
- this->bios_list->destroy_function(this->bios_list,
- (void *)free_bios_entry);
- this->ima_list->destroy_function(this->ima_list,
- (void *)free_ima_entry);
+ DESTROY_IF(this->bios_list);
+ DESTROY_IF(this->ima_list);
this->name->destroy(this->name);
- free(this->keyid.ptr);
+
free(this);
}
}
@@ -928,7 +884,7 @@ METHOD(pts_component_t, destroy, void,
/**
* See header
*/
-pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_ima_t *this;
@@ -948,10 +904,8 @@ pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
PTS_QUALIFIER_UNKNOWN),
.depth = depth,
.pts_db = pts_db,
- .bios_list = linked_list_create(),
- .ima_list = linked_list_create(),
.pcr_info = lib->settings->get_bool(lib->settings,
- "%s.plugins.imc-attestation.pcr_info", TRUE, lib->ns),
+ "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
.ref = 1,
);
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index f4859f801..67be1ca3a 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -41,11 +41,6 @@ struct pts_ita_comp_tboot_t {
pts_comp_func_name_t *name;
/**
- * AIK keyid
- */
- chunk_t keyid;
-
- /**
* Sub-component depth
*/
u_int32_t depth;
@@ -56,6 +51,11 @@ struct pts_ita_comp_tboot_t {
pts_database_t *pts_db;
/**
+ * Primary key for AIK database entry
+ */
+ int aik_id;
+
+ /**
* Primary key for Component Functional Name database entry
*/
int cid;
@@ -201,51 +201,38 @@ METHOD(pts_component_t, verify, status_t,
chunk_t measurement, pcr_before, pcr_after;
status_t status;
+ this->aik_id = pts->get_aik_id(pts);
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
- if (!this->keyid.ptr)
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->aik_id, algo,
+ &this->cid, &this->count);
+ if (status != SUCCESS)
{
- if (!pts->get_aik_keyid(pts, &this->keyid))
- {
- return FAILED;
- }
- this->keyid = chunk_clone(this->keyid);
-
- if (!this->pts_db)
- {
- DBG1(DBG_PTS, "pts database not available");
- return FAILED;
- }
- 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 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);
+ 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->count)
- {
- DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
- "measurements", this->count, pen_names, vid, names, name);
- }
- else
- {
- DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
- "measurements", pen_names, vid, names, name);
- this->is_registering = TRUE;
- }
+ if (this->count)
+ {
+ DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
+ "measurements", this->count, pen_names, vid, names, name);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
+ "measurements", pen_names, vid, names, name);
+ this->is_registering = TRUE;
}
if (this->is_registering)
{
status = this->pts_db->insert_comp_measurement(this->pts_db,
- measurement, this->cid, this->kid,
+ measurement, this->cid, this->aik_id,
++this->seq_no, extended_pcr, algo);
if (status != SUCCESS)
{
@@ -282,30 +269,31 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_tboot_t *this, u_int8_t qualifier)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result)
{
- u_int32_t vid, name;
- enum_name_t *names;
-
- 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);
+ char result_buf[BUF_LEN];
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);
+ snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
+ this->seq_no);
}
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);
+ snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
+ "missing", this->count - this->seq_no, this->count);
return FALSE;
}
+ else
+ {
+ snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
+ this->count);
+ }
+ DBG1(DBG_PTS, "%s", result_buf);
+ result->write_data(result, chunk_from_str(result_buf));
return TRUE;
}
@@ -329,7 +317,7 @@ METHOD(pts_component_t, destroy, void,
if (this->is_registering)
{
count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
+ this->cid, this->aik_id);
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);
@@ -337,7 +325,6 @@ METHOD(pts_component_t, destroy, void,
"evidence measurements", count, pen_names, vid, names, name);
}
this->name->destroy(this->name);
- free(this->keyid.ptr);
free(this);
}
}
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c
index e3acd8774..097e4c89c 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -49,7 +49,6 @@ struct pts_ita_comp_tgrub_t {
*/
pts_database_t *pts_db;
-
/**
* Reference count
*/
@@ -126,7 +125,8 @@ METHOD(pts_component_t, verify, status_t,
pts_pcr_transform_t transform;
pts_pcr_t *pcrs;
time_t measurement_time;
- chunk_t measurement, pcr_before, pcr_after;
+ chunk_t pcr_before, pcr_after;
+ chunk_t measurement __attribute__((unused));
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
@@ -155,7 +155,7 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_tgrub_t *this, u_int8_t qualifier)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result)
{
return FALSE;
}
@@ -206,4 +206,3 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
return &this->public;
}
-
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
index da339a55f..71b1ad59c 100644
--- a/src/libpts/pts/components/pts_component.h
+++ b/src/libpts/pts/components/pts_component.h
@@ -30,6 +30,7 @@ typedef struct pts_component_t pts_component_t;
#include "pts/components/pts_comp_evidence.h"
#include <library.h>
+#include <bio/bio_writer.h>
/**
* PTS Functional Component Interface
@@ -85,9 +86,11 @@ struct pts_component_t {
* and check for missing measurements
*
* @param qualifier PTS Component Functional Name Qualifier
+ * @param result writer appending concise measurement result
* @return TRUE if finalization successful
*/
- bool (*finalize)(pts_component_t *this, u_int8_t qualifier);
+ bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
+ bio_writer_t *result);
/**
* Get a new reference to the PTS Functional Component