summaryrefslogtreecommitdiff
path: root/src/libpts/pts
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
committerYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
commitb34738ed08c2227300d554b139e2495ca5da97d6 (patch)
tree62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libpts/pts
parent0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff)
downloadvyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz
vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libpts/pts')
-rw-r--r--src/libpts/pts/components/ita/ita_comp_func_name.c45
-rw-r--r--src/libpts/pts/components/ita/ita_comp_func_name.h85
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c439
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.h36
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c335
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.h36
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c184
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.h36
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.c251
-rw-r--r--src/libpts/pts/components/pts_comp_evidence.h170
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.c152
-rw-r--r--src/libpts/pts/components/pts_comp_func_name.h96
-rw-r--r--src/libpts/pts/components/pts_component.h94
-rw-r--r--src/libpts/pts/components/pts_component_manager.c317
-rw-r--r--src/libpts/pts/components/pts_component_manager.h125
-rw-r--r--src/libpts/pts/components/tcg/tcg_comp_func_name.c48
-rw-r--r--src/libpts/pts/components/tcg/tcg_comp_func_name.h98
-rw-r--r--src/libpts/pts/pts.c1539
-rw-r--r--src/libpts/pts/pts.h353
-rw-r--r--src/libpts/pts/pts_creds.c136
-rw-r--r--src/libpts/pts/pts_creds.h55
-rw-r--r--src/libpts/pts/pts_database.c312
-rw-r--r--src/libpts/pts/pts_database.h153
-rw-r--r--src/libpts/pts/pts_dh_group.c175
-rw-r--r--src/libpts/pts/pts_dh_group.h104
-rw-r--r--src/libpts/pts/pts_error.c99
-rw-r--r--src/libpts/pts/pts_error.h89
-rw-r--r--src/libpts/pts/pts_file_meas.c186
-rw-r--r--src/libpts/pts/pts_file_meas.h85
-rw-r--r--src/libpts/pts/pts_file_meta.c96
-rw-r--r--src/libpts/pts/pts_file_meta.h85
-rw-r--r--src/libpts/pts/pts_file_type.c33
-rw-r--r--src/libpts/pts/pts_file_type.h63
-rw-r--r--src/libpts/pts/pts_meas_algo.c170
-rw-r--r--src/libpts/pts/pts_meas_algo.h105
-rw-r--r--src/libpts/pts/pts_proto_caps.h44
-rw-r--r--src/libpts/pts/pts_req_func_comp_evid.h42
-rw-r--r--src/libpts/pts/pts_simple_evid_final.h47
38 files changed, 6518 insertions, 0 deletions
diff --git a/src/libpts/pts/components/ita/ita_comp_func_name.c b/src/libpts/pts/components/ita/ita_comp_func_name.c
new file mode 100644
index 000000000..a593281ba
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_func_name.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_func_name.h"
+
+char pts_ita_qualifier_flag_names[] = { 'K', 'S' };
+
+ENUM_BEGIN(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_UNKNOWN,
+ PTS_ITA_QUALIFIER_TYPE_TNC,
+ "Unknown",
+ "Trusted Platform",
+ "Operating System",
+ "Graphical User Interface",
+ "Application",
+ "Networking",
+ "Library",
+ "TNC Defined Component"
+);
+ENUM_NEXT(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL,
+ PTS_ITA_QUALIFIER_TYPE_ALL,
+ PTS_ITA_QUALIFIER_TYPE_TNC,
+ "All Matching Components"
+);
+ENUM_END(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL);
+
+ENUM(pts_ita_comp_func_names, PTS_ITA_COMP_FUNC_NAME_IGNORE,
+ PTS_ITA_COMP_FUNC_NAME_IMA,
+ "Ignore",
+ "Trusted GRUB Boot Loader",
+ "Trusted Boot",
+ "Linux IMA"
+);
+
diff --git a/src/libpts/pts/components/ita/ita_comp_func_name.h b/src/libpts/pts/components/ita/ita_comp_func_name.h
new file mode 100644
index 000000000..eb2f363f3
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_func_name.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_FUNC_NAME_H_
+#define PTS_ITA_COMP_FUNC_NAME_H_
+
+typedef enum pts_ita_qualifier_type_t pts_ita_qualifier_type_t;
+typedef enum pts_ita_comp_func_name_t pts_ita_comp_func_name_t;
+
+#include <library.h>
+
+/**
+ * PTS Component Functional Name Qualifier Flags for the ITA namespace
+ */
+#define PTS_ITA_QUALIFIER_FLAG_KERNEL (1<<5)
+#define PTS_ITA_QUALIFIER_FLAG_SUB (1<<4)
+
+extern char pts_ita_qualifier_flag_names[];
+
+/**
+ * Size of the PTS Component Functional Name Qualifier Type field
+ */
+#define PTS_ITA_QUALIFIER_TYPE_SIZE 4
+
+/**
+ * PTS Component Functional Name Qualifier Types for the ITA namespace
+ * equal to section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_ita_qualifier_type_t {
+ /** Unknown */
+ PTS_ITA_QUALIFIER_TYPE_UNKNOWN = 0x0,
+ /** Trusted Platform */
+ PTS_ITA_QUALIFIER_TYPE_TRUSTED = 0x1,
+ /** Operating System */
+ PTS_ITA_QUALIFIER_TYPE_OS = 0x2,
+ /** Graphical User Interface */
+ PTS_ITA_QUALIFIER_TYPE_GUI = 0x3,
+ /** Application */
+ PTS_ITA_QUALIFIER_TYPE_APP = 0x4,
+ /** Networking */
+ PTS_ITA_QUALIFIER_TYPE_NET = 0x5,
+ /** Library */
+ PTS_ITA_QUALIFIER_TYPE_LIB = 0x6,
+ /** TNC Defined Component */
+ PTS_ITA_QUALIFIER_TYPE_TNC = 0x7,
+ /** All Matching Components */
+ PTS_ITA_QUALIFIER_TYPE_ALL = 0xF,
+};
+
+extern enum_name_t *pts_ita_qualifier_type_names;
+
+/**
+ * PTS Component Functional Name Binary Enumeration for the ITA namespace
+ */
+enum pts_ita_comp_func_name_t {
+ /** Ignore */
+ PTS_ITA_COMP_FUNC_NAME_IGNORE = 0x0000,
+ /** Trusted GRUB Boot Loader */
+ PTS_ITA_COMP_FUNC_NAME_TGRUB = 0x0001,
+ /** Trusted Boot */
+ PTS_ITA_COMP_FUNC_NAME_TBOOT = 0x0002,
+ /** Linux Integrity Measurement Architecture */
+ PTS_ITA_COMP_FUNC_NAME_IMA = 0x0003,
+};
+
+extern enum_name_t *pts_ita_comp_func_names;
+
+#endif /** PTS_ITA_COMP_FUNC_NAME_H_ @}*/
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
new file mode 100644
index 000000000..a7da76651
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_ima.h"
+#include "ita_comp_func_name.h"
+
+#include "libpts.h"
+#include "pts/components/pts_component.h"
+
+#include <debug.h>
+#include <pen/pen.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#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
+
+typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
+
+/**
+ * Private data of a pts_ita_comp_ima_t object.
+ *
+ */
+struct pts_ita_comp_ima_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * AIK keyid
+ */
+ chunk_t keyid;
+
+ /**
+ * Sub-component depth
+ */
+ u_int32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * Primary key for Component Functional Name database entry
+ */
+ int cid;
+
+ /**
+ * Primary key for AIK database entry
+ */
+ int kid;
+
+ /**
+ * Component is registering measurements
+ */
+ bool is_registering;
+
+ /**
+ * IMA BIOS measurement time
+ */
+ time_t bios_measurement_time;
+
+ /**
+ * IMA BIOS measurements
+ */
+ linked_list_t *list;
+
+ /**
+ * Expected measurement count
+ */
+ int count;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
+
+ /**
+ * Shadow PCR registers
+ */
+ chunk_t pcrs[IMA_PCR_MAX];
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * Linux IMA measurement entry
+ */
+struct entry_t {
+
+ /**
+ * PCR register
+ */
+ u_int32_t pcr;
+
+ /**
+ * SHA1 measurement hash
+ */
+ chunk_t measurement;
+};
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *this)
+{
+ free(this->measurement.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)
+{
+ u_int32_t pcr, num, len;
+ 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(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));
+ close(fd);
+ return FALSE;
+}
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_ima_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+ pts_ita_comp_ima_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, u_int32_t,
+ pts_ita_comp_ima_t *this)
+{
+ return this->depth;
+}
+
+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);
+
+ if (this->list->get_count(this->list) == 0)
+ {
+ if (!load_measurements(IMA_BIOS_MEASUREMENT_PATH, this->list,
+ &this->bios_measurement_time))
+ {
+ return FAILED;
+ }
+ }
+
+ if (this->list->remove_first(this->list, (void**)&entry) != SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not retrieve measurement entry");
+ 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;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_ima_t *this, 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;
+ time_t measurement_time;
+ chunk_t measurement, pcr_before, pcr_after;
+
+ measurement = evidence->get_measurement(evidence, &extended_pcr,
+ &algo, &transform, &measurement_time);
+
+ if (!this->keyid.ptr)
+ {
+ 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;
+ }
+ 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
+ {
+ DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
+ "measurements", pen_names, vid, names, name);
+ this->is_registering = TRUE;
+ }
+ }
+
+ 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)
+ {
+ 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;
+ }
+ }
+
+ 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))
+ {
+ return FAILED;
+ }
+ }
+
+ return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+}
+
+METHOD(pts_component_t, check_off_registrations, bool,
+ pts_ita_comp_ima_t *this)
+{
+ u_int32_t vid, name;
+ enum_name_t *names;
+
+ if (!this->is_registering)
+ {
+ 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, destroy, void,
+ pts_ita_comp_ima_t *this)
+{
+ int i, 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)
+ {
+ 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->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_database_t *pts_db)
+{
+ pts_ita_comp_ima_t *this;
+ int i;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .check_off_registrations = _check_off_registrations,
+ .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(),
+ );
+
+ 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
new file mode 100644
index 000000000..1ca27e6f0
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_ima.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_IMA_H_
+#define PTS_ITA_COMP_IMA_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * 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_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
new file mode 100644
index 000000000..a85de8cd8
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_tboot.h"
+#include "ita_comp_func_name.h"
+
+#include "libpts.h"
+#include "pts/components/pts_component.h"
+
+#include <debug.h>
+#include <pen/pen.h>
+
+typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
+
+/**
+ * Private data of a pts_ita_comp_tboot_t object.
+ *
+ */
+struct pts_ita_comp_tboot_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * AIK keyid
+ */
+ chunk_t keyid;
+
+ /**
+ * Sub-component depth
+ */
+ u_int32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+ /**
+ * Primary key for Component Functional Name database entry
+ */
+ int cid;
+
+ /**
+ * Primary key for AIK database entry
+ */
+ int kid;
+
+ /**
+ * Component is registering measurements
+ */
+ bool is_registering;
+
+ /**
+ * Time of TBOOT measurement
+ */
+ time_t measurement_time;
+
+ /**
+ * Expected measurement count
+ */
+ int count;
+
+ /**
+ * Measurement sequence number
+ */
+ int seq_no;
+
+};
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_tboot_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+ pts_ita_comp_tboot_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, u_int32_t,
+ pts_ita_comp_tboot_t *this)
+{
+ return this->depth;
+}
+
+METHOD(pts_component_t, measure, status_t,
+ pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+{
+ 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++)
+ {
+ case 0:
+ /* dummy data since currently the TBOOT log is not retrieved */
+ time(&this->measurement_time);
+ meas_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr17_meas", NULL);
+ pcr_before_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr17_before", NULL);
+ pcr_after_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr17_after", NULL);
+ extended_pcr = PCR_TBOOT_POLICY;
+ break;
+ case 1:
+ /* dummy data since currently the TBOOT log is not retrieved */
+ meas_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr18_meas", NULL);
+ pcr_before_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr18_before", NULL);
+ pcr_after_hex = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.pcr18_after", NULL);
+ extended_pcr = PCR_TBOOT_MLE;
+ break;
+ default:
+ return FAILED;
+ }
+
+ if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
+ {
+ 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);
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ /* get and check the measurement data */
+ measurement = chunk_from_hex(
+ chunk_create(meas_hex, strlen(meas_hex)), NULL);
+ pcr_before = chunk_from_hex(
+ chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
+ 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)
+ {
+ 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;
+ }
+
+ evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
+ 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)
+{
+ 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;
+ time_t measurement_time;
+ chunk_t measurement, pcr_before, pcr_after;
+
+ measurement = evidence->get_measurement(evidence, &extended_pcr,
+ &algo, &transform, &measurement_time);
+
+ if (!this->keyid.ptr)
+ {
+ 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;
+ }
+ 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
+ {
+ DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
+ "measurements", pen_names, vid, names, name);
+ this->is_registering = TRUE;
+ }
+ }
+
+ 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)
+ {
+ 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;
+ }
+ }
+
+ 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))
+ {
+ return FAILED;
+ }
+ }
+
+ return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
+}
+
+METHOD(pts_component_t, check_off_registrations, bool,
+ pts_ita_comp_tboot_t *this)
+{
+ u_int32_t vid, name;
+ enum_name_t *names;
+
+ if (!this->is_registering)
+ {
+ 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, destroy, void,
+ pts_ita_comp_tboot_t *this)
+{
+ int count;
+ u_int32_t vid, name;
+ enum_name_t *names;
+
+ 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);
+}
+
+/**
+ * See header
+ */
+pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth,
+ pts_database_t *pts_db)
+{
+ pts_ita_comp_tboot_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .check_off_registrations = _check_off_registrations,
+ .destroy = _destroy,
+ },
+ .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
+ qualifier),
+ .depth = depth,
+ .pts_db = pts_db,
+ );
+
+ 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
new file mode 100644
index 000000000..39554fbc7
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_TBOOT_H_
+#define PTS_ITA_COMP_TBOOT_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * 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_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
new file mode 100644
index 000000000..0dfd5fd41
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ita_comp_tgrub.h"
+#include "ita_comp_func_name.h"
+
+#include "pts/components/pts_component.h"
+
+#include <debug.h>
+#include <pen/pen.h>
+
+typedef struct pts_ita_comp_tgrub_t pts_ita_comp_tgrub_t;
+
+/**
+ * Private data of a pts_ita_comp_tgrub_t object.
+ *
+ */
+struct pts_ita_comp_tgrub_t {
+
+ /**
+ * Public pts_component_t interface.
+ */
+ pts_component_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-component depth
+ */
+ u_int32_t depth;
+
+ /**
+ * PTS measurement database
+ */
+ pts_database_t *pts_db;
+
+};
+
+METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
+ pts_ita_comp_tgrub_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+ pts_ita_comp_tgrub_t *this)
+{
+ return PTS_REQ_FUNC_COMP_EVID_PCR;
+}
+
+METHOD(pts_component_t, get_depth, u_int32_t,
+ pts_ita_comp_tgrub_t *this)
+{
+ return this->depth;
+}
+
+METHOD(pts_component_t, measure, status_t,
+ pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
+{
+ 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;
+ time(&measurement_time);
+
+ if (!pts->read_pcr(pts, extended_pcr, &pcr_after))
+ {
+ DBG1(DBG_PTS, "error occurred while reading PCR: %d", extended_pcr);
+ 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);
+ pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+
+ measurement = chunk_alloc(hash_size);
+ memset(measurement.ptr, 0x00, measurement.len);
+
+ pcr_before = chunk_alloc(pcr_len);
+ memset(pcr_before.ptr, 0x00, pcr_before.len);
+
+ evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
+ this->depth, extended_pcr,
+ hash_algo, pcr_transform,
+ measurement_time, measurement);
+ evid->set_pcr_info(evid, pcr_before, pcr_after);
+
+ return SUCCESS;
+}
+
+METHOD(pts_component_t, verify, status_t,
+ pts_ita_comp_tgrub_t *this, 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;
+ time_t measurement_time;
+ chunk_t measurement, pcr_before, pcr_after;
+
+ measurement = evidence->get_measurement(evidence, &extended_pcr,
+ &algo, &transform, &measurement_time);
+ if (extended_pcr != PCR_DEBUG)
+ {
+ return FAILED;
+ }
+
+ /* TODO check measurement in database */
+
+ 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))
+ {
+ return FAILED;
+ }
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pts_component_t, check_off_registrations, bool,
+ pts_ita_comp_tgrub_t *this)
+{
+ return FALSE;
+}
+
+METHOD(pts_component_t, destroy, void,
+ pts_ita_comp_tgrub_t *this)
+{
+ 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_database_t *pts_db)
+{
+ pts_ita_comp_tgrub_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_evidence_flags = _get_evidence_flags,
+ .get_depth = _get_depth,
+ .measure = _measure,
+ .verify = _verify,
+ .check_off_registrations = _check_off_registrations,
+ .destroy = _destroy,
+ },
+ .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB,
+ qualifier),
+ .depth = depth,
+ .pts_db = pts_db,
+ );
+
+ 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
new file mode 100644
index 000000000..52ecc325c
--- /dev/null
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_ita_comp_func_name pts_ita_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ITA_COMP_TGRUB_H_
+#define PTS_ITA_COMP_TGRUB_H_
+
+#include "pts/components/pts_component.h"
+
+/**
+ * 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_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
new file mode 100644
index 000000000..9eb8dae75
--- /dev/null
+++ b/src/libpts/pts/components/pts_comp_evidence.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts/components/pts_comp_evidence.h"
+
+#include <debug.h>
+
+typedef struct private_pts_comp_evidence_t private_pts_comp_evidence_t;
+
+/**
+ * Private data of a pts_comp_evidence_t object.
+ */
+struct private_pts_comp_evidence_t {
+
+ /**
+ * Public pts_comp_evidence_t interface.
+ */
+ pts_comp_evidence_t public;
+
+ /**
+ * Component Functional Name
+ */
+ pts_comp_func_name_t *name;
+
+ /**
+ * Sub-Component Depth
+ */
+ u_int32_t depth;
+
+ /**
+ * Measurement Time
+ */
+ time_t measurement_time;
+
+ /**
+ * Measurement Time
+ */
+ chunk_t measurement;
+
+ /**
+ * Measurement Hash Algorithm
+ */
+ pts_meas_algorithms_t hash_algorithm;
+
+ /**
+ * Is PCR Information included?
+ */
+ bool has_pcr_info;
+
+ /**
+ * PCR the measurement was extended into
+ */
+ u_int32_t extended_pcr;
+
+ /**
+ * PCR value before extension
+ */
+ chunk_t pcr_before;
+
+ /**
+ * PCR value after extension
+ */
+ chunk_t pcr_after;
+
+ /**
+ * Transformation used for extending measurement into PCR
+ */
+ pts_pcr_transform_t transform;
+
+ /**
+ * Component Validation Result
+ */
+ pts_comp_evid_validation_t validation;
+
+ /**
+ * Verification Policy URI
+ */
+ chunk_t policy_uri;
+
+};
+
+METHOD(pts_comp_evidence_t, get_comp_func_name, pts_comp_func_name_t*,
+ private_pts_comp_evidence_t *this, u_int32_t *depth)
+{
+ if (depth)
+ {
+ *depth = this->depth;
+ }
+ return this->name;
+}
+
+METHOD(pts_comp_evidence_t, get_extended_pcr, u_int32_t,
+ private_pts_comp_evidence_t *this)
+{
+ return this->extended_pcr;
+}
+
+METHOD(pts_comp_evidence_t, get_measurement, chunk_t,
+ private_pts_comp_evidence_t *this, u_int32_t *extended_pcr,
+ pts_meas_algorithms_t *algo, pts_pcr_transform_t *transform,
+ time_t *measurement_time)
+{
+ if (extended_pcr)
+ {
+ *extended_pcr = this->extended_pcr;
+ }
+ if (algo)
+ {
+ *algo = this->hash_algorithm;
+ }
+ if (transform)
+ {
+ *transform = this->transform;
+ }
+ if (measurement_time)
+ {
+ *measurement_time = this->measurement_time;
+ }
+ return this->measurement;
+}
+
+METHOD(pts_comp_evidence_t, get_pcr_info, bool,
+ private_pts_comp_evidence_t *this, chunk_t *pcr_before, chunk_t *pcr_after)
+{
+ if (pcr_before)
+ {
+ *pcr_before = this->pcr_before;
+ }
+ if (pcr_after)
+ {
+ *pcr_after = this->pcr_after;
+ }
+ return this->has_pcr_info;
+}
+
+METHOD(pts_comp_evidence_t, set_pcr_info, void,
+ private_pts_comp_evidence_t *this, chunk_t pcr_before, chunk_t pcr_after)
+{
+ this->has_pcr_info = TRUE;
+ 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);
+}
+
+METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
+ private_pts_comp_evidence_t *this, chunk_t *uri)
+{
+ if (uri)
+ {
+ *uri = this->policy_uri;
+ }
+ return this->validation;
+}
+
+METHOD(pts_comp_evidence_t, set_validation, void,
+ private_pts_comp_evidence_t *this, pts_comp_evid_validation_t validation,
+ chunk_t uri)
+{
+ this->validation = validation;
+ this->policy_uri = chunk_clone(uri);
+}
+
+METHOD(pts_comp_evidence_t, destroy, void,
+ private_pts_comp_evidence_t *this)
+{
+ this->name->destroy(this->name);
+ free(this->measurement.ptr);
+ free(this->pcr_before.ptr);
+ free(this->pcr_after.ptr);
+ free(this->policy_uri.ptr);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_comp_evidence_t *pts_comp_evidence_create(pts_comp_func_name_t *name,
+ u_int32_t depth,
+ u_int32_t extended_pcr,
+ pts_meas_algorithms_t algo,
+ pts_pcr_transform_t transform,
+ time_t measurement_time,
+ chunk_t measurement)
+{
+ private_pts_comp_evidence_t *this;
+
+ INIT(this,
+ .public = {
+ .get_comp_func_name = _get_comp_func_name,
+ .get_extended_pcr = _get_extended_pcr,
+ .get_measurement = _get_measurement,
+ .get_pcr_info = _get_pcr_info,
+ .set_pcr_info = _set_pcr_info,
+ .get_validation = _get_validation,
+ .set_validation = _set_validation,
+ .destroy = _destroy,
+ },
+ .name = name,
+ .depth = depth,
+ .extended_pcr = extended_pcr,
+ .hash_algorithm = algo,
+ .transform = transform,
+ .measurement_time = measurement_time,
+ .measurement = measurement,
+ );
+
+ name->log(name, "");
+ DBG2(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
+ DBG2(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
+ size_t pcr_len)
+{
+ size_t hash_size;
+
+ hash_size = pts_meas_algo_hash_size(algo);
+ if (hash_size == 0)
+ {
+ return PTS_PCR_TRANSFORM_NO;
+ }
+ if (hash_size == pcr_len)
+ {
+ return PTS_PCR_TRANSFORM_MATCH;
+ }
+ if (hash_size > pcr_len)
+ {
+ return PTS_PCR_TRANSFORM_LONG;
+ }
+ return PTS_PCR_TRANSFORM_SHORT;
+}
+
diff --git a/src/libpts/pts/components/pts_comp_evidence.h b/src/libpts/pts/components/pts_comp_evidence.h
new file mode 100644
index 000000000..fe86aa940
--- /dev/null
+++ b/src/libpts/pts/components/pts_comp_evidence.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_comp_evidence pts_comp_evidence
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMP_EVIDENCE_H_
+#define PTS_COMP_EVIDENCE_H_
+
+typedef struct pts_comp_evidence_t pts_comp_evidence_t;
+typedef enum pts_pcr_transform_t pts_pcr_transform_t;
+typedef enum pts_comp_evid_validation_t pts_comp_evid_validation_t;
+
+#include "pts/pts_meas_algo.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <library.h>
+
+/**
+ * PTS PCR Transformations
+ */
+enum pts_pcr_transform_t {
+ /** No Transformation */
+ PTS_PCR_TRANSFORM_NO = 0,
+ /** Hash Value matched PCR size */
+ PTS_PCR_TRANSFORM_MATCH = 1,
+ /** Hash value shorter than PCR size */
+ PTS_PCR_TRANSFORM_SHORT = 2,
+ /** Hash value longer than PCR size */
+ PTS_PCR_TRANSFORM_LONG = 3,
+};
+
+/**
+ * PTS Component Evidence Validation Result Flags
+ */
+enum pts_comp_evid_validation_t {
+ /** No Validation was attempted */
+ PTS_COMP_EVID_VALIDATION_NONE = 0x00,
+ /** Attempted validation, unable to verify */
+ PTS_COMP_EVID_VALIDATION_UNABLE = 0x20,
+ /** Attempted validation, verification failed */
+ PTS_COMP_EVID_VALIDATION_FAILED = 0x40,
+ /** Attempted validation, verification passed */
+ PTS_COMP_EVID_VALIDATION_PASSED = 0x60,
+};
+
+/**
+ * PTS Functional Component Interface
+ */
+struct pts_comp_evidence_t {
+
+ /**
+ * Gets the Component Functional Name and Sub-Component Depth
+ *
+ * @param depth Sub-Component Depth
+ * @result Component Functional Name
+ */
+ pts_comp_func_name_t* (*get_comp_func_name)(pts_comp_evidence_t *this,
+ u_int32_t *depth);
+
+ /**
+ * Gets the PCR the measurement was extended into
+ *
+ * @result PCR the measurement was extended into
+ */
+ u_int32_t (*get_extended_pcr)(pts_comp_evidence_t *this);
+
+ /**
+ * Gets the measurement and the algorithms used
+ *
+ * @param extended_pcr PCR the measurement was extended into
+ * @param algo Measurement hash algorithm
+ * @param transform Transformation used for PCR extension
+ * @param measurement_time Time the measurement was taken
+ * @result Measurement hash value
+ */
+ chunk_t (*get_measurement)(pts_comp_evidence_t *this,
+ u_int32_t *extended_pcr,
+ pts_meas_algorithms_t *algo,
+ pts_pcr_transform_t *transform,
+ time_t *measurement_time);
+
+ /**
+ * Gets the PCR information if available
+ *
+ * @param pcr_before PCR value before extension
+ * @param pcr_after PCR value after extension
+ * @result TRUE if PCR information is available
+ */
+ bool (*get_pcr_info)(pts_comp_evidence_t *this, chunk_t *pcr_before,
+ chunk_t *pcr_after);
+
+ /**
+ * Sets PCR information if available
+ *
+ * @param pcr_before PCR value before extension
+ * @param pcr_after PCR value after extension
+ */
+ void (*set_pcr_info)(pts_comp_evidence_t *this, chunk_t pcr_before,
+ chunk_t pcr_after);
+
+ /**
+ * Gets Validation Result if available
+ *
+ * @param uri Verification Policy URI
+ * @return validation Validation Result
+ */
+ pts_comp_evid_validation_t (*get_validation)(pts_comp_evidence_t *this,
+ chunk_t *uri);
+
+ /**
+ * Sets Validation Result if available
+ *
+ * @param validation Validation Result
+ * @param uri Verification Policy URI
+ */
+ void (*set_validation)(pts_comp_evidence_t *this,
+ pts_comp_evid_validation_t validation, chunk_t uri);
+
+ /**
+ * Destroys a pts_comp_evidence_t object.
+ */
+ void (*destroy)(pts_comp_evidence_t *this);
+
+};
+
+/**
+ * Creates a pts_comp_evidence_t object
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component depth
+ * @param extended_pcr PCR the measurement was extended into
+ * @param algo Measurement hash algorithm
+ * @param transform Transformation used for PCR extension
+ * @param measurement_time Time the measurement was taken, 0 if unknown
+ * @param measurement Measurement hash value
+ */
+pts_comp_evidence_t* pts_comp_evidence_create(pts_comp_func_name_t *name,
+ u_int32_t depth,
+ u_int32_t extended_pcr,
+ pts_meas_algorithms_t algo,
+ pts_pcr_transform_t transform,
+ time_t measurement_time,
+ chunk_t measurement);
+
+/**
+ * Determine transform to fit measurement hash into PCR register
+ *
+ * @param algo Measurement hash algorithm
+ * @param pcr_len Length of the PCR registers in bytes
+ * @return PCR transform type
+ */
+pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
+ size_t pcr_len);
+
+#endif /** PTS_COMP_EVIDENCE_H_ @}*/
diff --git a/src/libpts/pts/components/pts_comp_func_name.c b/src/libpts/pts/components/pts_comp_func_name.c
new file mode 100644
index 000000000..d98850d78
--- /dev/null
+++ b/src/libpts/pts/components/pts_comp_func_name.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "libpts.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <debug.h>
+
+typedef struct private_pts_comp_func_name_t private_pts_comp_func_name_t;
+
+/**
+ * Private data of a pts_comp_func_name_t object.
+ *
+ */
+struct private_pts_comp_func_name_t {
+
+ /**
+ * Public pts_comp_func_name_t interface.
+ */
+ pts_comp_func_name_t public;
+
+ /**
+ * PTS Component Functional Name Vendor ID
+ */
+ u_int32_t vid;
+
+ /**
+ * PTS Component Functional Name
+ */
+ u_int32_t name;
+
+ /**
+ * PTS Component Functional Name Qualifier
+ */
+ u_int8_t qualifier;
+
+};
+
+METHOD(pts_comp_func_name_t, get_vendor_id, u_int32_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->vid;
+}
+
+METHOD(pts_comp_func_name_t, get_name, u_int32_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->name;
+}
+
+METHOD(pts_comp_func_name_t, get_qualifier, u_int8_t,
+ private_pts_comp_func_name_t *this)
+{
+ return this->qualifier;
+}
+
+static bool equals(private_pts_comp_func_name_t *this,
+ private_pts_comp_func_name_t *other)
+{
+ if (this->vid != other->vid || this->name != other->name)
+ {
+ return FALSE;
+ }
+ if (this->qualifier == PTS_QUALIFIER_UNKNOWN ||
+ other->qualifier == PTS_QUALIFIER_UNKNOWN)
+ {
+ return TRUE;
+ }
+ /* TODO handle qualifier wildcards */
+
+ return this->qualifier == other->qualifier;
+}
+
+METHOD(pts_comp_func_name_t, clone_, pts_comp_func_name_t*,
+ private_pts_comp_func_name_t *this)
+{
+ private_pts_comp_func_name_t *clone;
+
+ clone = malloc_thing(private_pts_comp_func_name_t);
+ memcpy(clone, this, sizeof(private_pts_comp_func_name_t));
+
+ return &clone->public;
+}
+
+METHOD(pts_comp_func_name_t, log_, void,
+ private_pts_comp_func_name_t *this, char *label)
+{
+ enum_name_t *names, *types;
+ char flags[8];
+ int type;
+
+ names = pts_components->get_comp_func_names(pts_components, this->vid);
+ types = pts_components->get_qualifier_type_names(pts_components, this->vid);
+ type = pts_components->get_qualifier(pts_components, &this->public, flags);
+
+ if (names && types)
+ {
+ DBG2(DBG_PTS, "%s%N functional component '%N' [%s] '%N'",
+ label, pen_names, this->vid, names, this->name, flags, types, type);
+ }
+ else
+ {
+ DBG2(DBG_PTS, "%s0x%06x functional component 0x%08x 0x%02x",
+ label, this->vid, this->name, this->qualifier);
+ }
+}
+
+METHOD(pts_comp_func_name_t, destroy, void,
+ private_pts_comp_func_name_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
+ u_int8_t qualifier)
+{
+ private_pts_comp_func_name_t *this;
+
+ INIT(this,
+ .public = {
+ .get_vendor_id = _get_vendor_id,
+ .get_name = _get_name,
+ .get_qualifier = _get_qualifier,
+ .equals = (bool(*)(pts_comp_func_name_t*,pts_comp_func_name_t*))equals,
+ .clone = _clone_,
+ .log = _log_,
+ .destroy = _destroy,
+ },
+ .vid = vid,
+ .name = name,
+ .qualifier = qualifier,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/components/pts_comp_func_name.h b/src/libpts/pts/components/pts_comp_func_name.h
new file mode 100644
index 000000000..2c7a84177
--- /dev/null
+++ b/src/libpts/pts/components/pts_comp_func_name.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_comp_func_name pts_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FUNC_COMP_NAME_H_
+#define PTS_FUNC_COMP_NAME_H_
+
+typedef struct pts_comp_func_name_t pts_comp_func_name_t;
+
+#include <library.h>
+
+#define PTS_QUALIFIER_UNKNOWN 0x00
+#define PTS_QUALIFIER_WILDCARD 0x3F
+
+/**
+ * PTS Component Functional Name object
+ */
+struct pts_comp_func_name_t {
+
+ /**
+ * Get the PTS Component Functional Name Vendor ID
+ *
+ * @return PTS Component Functional Name Vendor ID
+ */
+ u_int32_t (*get_vendor_id)(pts_comp_func_name_t *this);
+
+ /**
+ * Get the PTS Component Functional Name
+ *
+ * @return PTS Component Functional Name
+ */
+ u_int32_t (*get_name)(pts_comp_func_name_t *this);
+
+ /**
+ * Get the PTS Component Functional Name Qualifier
+ *
+ * @return PTS Component Functional Name Qualifier
+ */
+ u_int8_t (*get_qualifier)(pts_comp_func_name_t *this);
+
+ /**
+ * Check to PTS Component Functional Names for equality
+ *
+ * @param other Other PTS Component Functional Name
+ * @return TRUE if equal
+ */
+ bool (*equals)(pts_comp_func_name_t *this, pts_comp_func_name_t *other);
+
+ /**
+ * Clone a PTS Component Functional Name
+ *
+ * @return Cloned PTS Component Functional Name
+ */
+ pts_comp_func_name_t* (*clone)(pts_comp_func_name_t *this);
+
+ /**
+ * Write PTS Component Functional Name information to the standard logfile
+ *
+ * @param label Label added to log output
+ */
+ void (*log)(pts_comp_func_name_t *this, char *label);
+
+ /**
+ * Destroys a pts_component_t object.
+ */
+ void (*destroy)(pts_comp_func_name_t *this);
+
+};
+
+/**
+ * Create a PTS Component Functional Name object
+ *
+ * @param vid PTS Component Functional Name Vendor ID
+ * @param name PTS Component Functional Name
+ * @param PTS Component Functional Name Qualifier
+ */
+pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
+ u_int8_t qualifier);
+
+#endif /** PTS_FUNC_COMP_NAME_H_ @}*/
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
new file mode 100644
index 000000000..524ff332d
--- /dev/null
+++ b/src/libpts/pts/components/pts_component.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_component pts_component
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMPONENT_H_
+#define PTS_COMPONENT_H_
+
+typedef struct pts_component_t pts_component_t;
+
+#include "pts/pts.h"
+#include "pts/pts_database.h"
+#include "pts/components/pts_comp_func_name.h"
+#include "pts/components/pts_comp_evidence.h"
+
+#include <library.h>
+
+/**
+ * PTS Functional Component Interface
+ */
+struct pts_component_t {
+
+ /**
+ * Get the PTS Component Functional Name
+ *
+ * @return PTS Component Functional Name
+ */
+ pts_comp_func_name_t* (*get_comp_func_name)(pts_component_t *this);
+
+ /**
+ * Get the PTS Component Evidence Flags
+ *
+ * @return PTS Component Functional Name
+ */
+ u_int8_t (*get_evidence_flags)(pts_component_t *this);
+
+ /**
+ * Get the PTS Sub-component Depth
+ *
+ * @return PTS Sub-component Depth
+ */
+ u_int32_t (*get_depth)(pts_component_t *this);
+
+ /**
+ * Do evidence measurements on the PTS Functional Component
+ *
+ * @param pts PTS interface
+ * @param evidence returns component evidence measureemt
+ * @return status return code
+ */
+ status_t (*measure)(pts_component_t *this, pts_t *pts,
+ pts_comp_evidence_t** evidence);
+
+ /**
+ * Verify the evidence measurements of the PTS Functional Component
+ *
+ * @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,
+ pts_comp_evidence_t *evidence);
+
+
+ /**
+ * Tell the PTS Functional Component to finalize pending registrations
+ *
+ * @return TRUE if there are pending registrations
+ */
+ bool (*check_off_registrations)(pts_component_t *this);
+
+ /**
+ * Destroys a pts_component_t object.
+ */
+ void (*destroy)(pts_component_t *this);
+
+};
+
+#endif /** PTS_COMPONENT_H_ @}*/
diff --git a/src/libpts/pts/components/pts_component_manager.c b/src/libpts/pts/components/pts_component_manager.c
new file mode 100644
index 000000000..8ac4767bf
--- /dev/null
+++ b/src/libpts/pts/components/pts_component_manager.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ *
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts/components/pts_component_manager.h"
+
+#include <utils/linked_list.h>
+#include <debug.h>
+
+typedef struct private_pts_component_manager_t private_pts_component_manager_t;
+typedef struct vendor_entry_t vendor_entry_t;
+typedef struct component_entry_t component_entry_t;
+
+#define PTS_QUALIFIER_SIZE 6
+
+/**
+ * Vendor-specific namespace information and list of registered components
+ */
+struct vendor_entry_t {
+
+ /**
+ * Vendor ID
+ */
+ pen_t vendor_id;
+
+ /**
+ * Vendor-specific Component Functional names
+ */
+ enum_name_t *comp_func_names;
+
+ /**
+ * Vendor-specific Qualifier Type names
+ */
+ enum_name_t *qualifier_type_names;
+
+ /**
+ * Vendor-specific Qualifier Flag names
+ */
+ char *qualifier_flag_names;
+
+ /**
+ * Vendor-specific size of Qualfiier Type field
+ */
+ int qualifier_type_size;
+
+ /**
+ * List of vendor-specific registered Functional Components
+ */
+ linked_list_t *components;
+};
+
+/**
+ * Destroy a vendor_entry_t object
+ */
+static void vendor_entry_destroy(vendor_entry_t *entry)
+{
+ entry->components->destroy_function(entry->components, free);
+ free(entry);
+}
+
+/**
+ * Creation method for a vendor-specific Functional Component
+ */
+struct component_entry_t {
+
+ /**
+ * Vendor-Specific Component Functional Name
+ */
+ u_int32_t name;
+
+ /**
+ * Functional Component creation method
+ */
+ pts_component_create_t create;
+};
+
+/**
+ * Private data of a pts_component_manager_t object.
+ *
+ */
+struct private_pts_component_manager_t {
+
+ /**
+ * Public pts_component_manager_t interface.
+ */
+ pts_component_manager_t public;
+
+ /**
+ * List of vendor-specific namespaces and registered components
+ */
+ linked_list_t *list;
+};
+
+METHOD(pts_component_manager_t, add_vendor, void,
+ private_pts_component_manager_t *this, pen_t vendor_id,
+ enum_name_t *comp_func_names, int qualifier_type_size,
+ char *qualifier_flag_names, enum_name_t *qualifier_type_names)
+{
+ vendor_entry_t *entry;
+
+ entry = malloc_thing(vendor_entry_t);
+ entry->vendor_id = vendor_id;
+ entry->comp_func_names = comp_func_names;
+ entry->qualifier_type_size = qualifier_type_size;
+ entry->qualifier_flag_names = qualifier_flag_names;
+ entry->qualifier_type_names = qualifier_type_names;
+ entry->components = linked_list_create();
+
+ this->list->insert_last(this->list, entry);
+ DBG2(DBG_PTS, "added %N functional component namespace",
+ pen_names, vendor_id);
+}
+
+METHOD(pts_component_manager_t, get_comp_func_names, enum_name_t*,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ enum_name_t *names = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ names = entry->comp_func_names;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return names;
+}
+
+METHOD(pts_component_manager_t, get_qualifier_type_names, enum_name_t*,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ enum_name_t *names = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ names = entry->qualifier_type_names;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return names;
+}
+
+METHOD(pts_component_manager_t, add_component, void,
+ private_pts_component_manager_t *this, pen_t vendor_id, u_int32_t name,
+ pts_component_create_t create)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ component_entry_t *component;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ component = malloc_thing(component_entry_t);
+ component->name = name;
+ component->create = create;
+
+ entry->components->insert_last(entry->components, component);
+ DBG2(DBG_PTS, "added %N functional component '%N'",
+ pen_names, vendor_id,
+ get_comp_func_names(this, vendor_id), name);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(pts_component_manager_t, remove_vendor, void,
+ private_pts_component_manager_t *this, pen_t vendor_id)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == vendor_id)
+ {
+ this->list->remove_at(this->list, enumerator);
+ vendor_entry_destroy(entry);
+ DBG2(DBG_PTS, "removed %N functional component namespace",
+ pen_names, vendor_id);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(pts_component_manager_t, get_qualifier, u_int8_t,
+ private_pts_component_manager_t *this, pts_comp_func_name_t *name,
+ char *flags)
+{
+ enumerator_t *enumerator;
+ vendor_entry_t *entry;
+ u_int8_t qualifier, size, flag, type = 0;
+ int i;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == name->get_vendor_id(name))
+ {
+ qualifier = name->get_qualifier(name);
+ size = entry->qualifier_type_size;
+
+ /* mask qualifier type field */
+ type = qualifier & ((1 << size) - 1);
+
+ /* determine flags */
+ size = PTS_QUALIFIER_SIZE - size;
+ flag = (1 << (PTS_QUALIFIER_SIZE - 1));
+ if (flags)
+ {
+ for (i = 0 ; i < size; i++)
+ {
+ flags[i] = (qualifier & flag) ?
+ entry->qualifier_flag_names[i] : '.';
+ flag >>= 1;
+ }
+ flags[size] = '\0';
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return type;
+}
+
+METHOD(pts_component_manager_t, create, pts_component_t*,
+ private_pts_component_manager_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth, pts_database_t *pts_db)
+{
+ enumerator_t *enumerator, *e2;
+ vendor_entry_t *entry;
+ component_entry_t *entry2;
+ pts_component_t *component = NULL;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->vendor_id == name->get_vendor_id(name))
+ {
+ e2 = entry->components->create_enumerator(entry->components);
+ while (e2->enumerate(e2, &entry2))
+ {
+ if (entry2->name == name->get_name(name) && entry2->create)
+ {
+ component = entry2->create(name->get_qualifier(name),
+ depth, pts_db);
+ break;
+ }
+ }
+ e2->destroy(e2);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return component;
+}
+
+METHOD(pts_component_manager_t, destroy, void,
+ private_pts_component_manager_t *this)
+{
+ this->list->destroy_function(this->list, (void *)vendor_entry_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_component_manager_t *pts_component_manager_create(void)
+{
+ private_pts_component_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .add_vendor = _add_vendor,
+ .add_component = _add_component,
+ .remove_vendor = _remove_vendor,
+ .get_comp_func_names = _get_comp_func_names,
+ .get_qualifier_type_names = _get_qualifier_type_names,
+ .get_qualifier = _get_qualifier,
+ .create = _create,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/components/pts_component_manager.h b/src/libpts/pts/components/pts_component_manager.h
new file mode 100644
index 000000000..0079d0e26
--- /dev/null
+++ b/src/libpts/pts/components/pts_component_manager.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_component_manager pts_component_manager
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_COMPONENT_MANAGER_H_
+#define PTS_COMPONENT_MANAGER_H_
+
+typedef struct pts_component_manager_t pts_component_manager_t;
+
+#include "pts/pts_database.h"
+#include "pts/components/pts_component.h"
+#include "pts/components/pts_comp_func_name.h"
+
+#include <library.h>
+#include <pen/pen.h>
+
+typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier,
+ u_int32_t depth,
+ pts_database_t *pts_db);
+
+/**
+ * Manages PTS Functional Components
+ */
+struct pts_component_manager_t {
+
+ /**
+ * Add vendor-specific functional component names
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @param comp_func_names Vendor-specific Component Functional names
+ * @param qualifier_type_size Vendor-specific Qualifier Type size
+ * @param qualifier_flag_names Vendor-specific Qualifier Flag names
+ * @param qualifier_type_names Vendor-specific Qualifier Type names
+ */
+ void (*add_vendor)(pts_component_manager_t *this, pen_t vendor_id,
+ enum_name_t *comp_func_names,
+ int qualifier_type_size,
+ char *qualifier_flag_names,
+ enum_name_t *qualifier_type_names);
+
+ /**
+ * Add vendor-specific functional component
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @param names Component Functional Name
+ * @param create Functional Component creation method
+ */
+ void (*add_component)(pts_component_manager_t *this, pen_t vendor_id,
+ u_int32_t name, pts_component_create_t create);
+
+ /**
+ * Remove vendor-specific components and associated namespace
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ */
+ void (*remove_vendor)(pts_component_manager_t *this, pen_t vendor_id);
+
+ /**
+ * Return the Functional Component names for a given vendor ID
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @return Comp. Func. names if found, NULL else
+ */
+ enum_name_t* (*get_comp_func_names)(pts_component_manager_t *this,
+ pen_t vendor_id);
+
+ /**
+ * Return the Functional Component Qualifier Type names for a given vendor ID
+ *
+ * @param vendor_id Private Enterprise Number (PEN)
+ * @return Qualifier Type names if found, NULL else
+ */
+ enum_name_t* (*get_qualifier_type_names)(pts_component_manager_t *this,
+ pen_t vendor_id);
+
+ /**
+ * Return the Qualifier Type and Flags
+ *
+ * @param name Component Functional Name
+ * @param flags Qualifier Flags as a string in a char buffer
+ * @return Qualifier Type
+ */
+ u_int8_t (*get_qualifier)(pts_component_manager_t *this,
+ pts_comp_func_name_t *name, char *flags);
+
+ /**
+ * Create a PTS Component object from a Functional Component Name object
+ *
+ * @param name Component Functional Name
+ * @param depth Sub-component Depth
+ * @param pts_db PTS measurement database
+ * @return Component object if supported, NULL else
+ */
+ pts_component_t* (*create)(pts_component_manager_t *this,
+ pts_comp_func_name_t *name, u_int32_t depth,
+ pts_database_t *pts_db);
+
+ /**
+ * Destroys a pts_component_manager_t object.
+ */
+ void (*destroy)(pts_component_manager_t *this);
+};
+
+/**
+ * Create a PA-TNC attribute manager
+ */
+pts_component_manager_t* pts_component_manager_create(void);
+
+#endif /** PTS_COMPONENT_MANAGER_H_ @}*/
diff --git a/src/libpts/pts/components/tcg/tcg_comp_func_name.c b/src/libpts/pts/components/tcg/tcg_comp_func_name.c
new file mode 100644
index 000000000..a70c84e48
--- /dev/null
+++ b/src/libpts/pts/components/tcg/tcg_comp_func_name.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tcg_comp_func_name.h"
+
+char pts_tcg_qualifier_flag_names[] = { 'K', 'S' };
+
+ENUM_BEGIN(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_UNKNOWN,
+ PTS_TCG_QUALIFIER_TYPE_TNC,
+ "Unknown",
+ "Trusted Platform",
+ "Operating System",
+ "Graphical User Interface",
+ "Application",
+ "Networking",
+ "Library",
+ "TNC Defined Component"
+);
+ENUM_NEXT(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL,
+ PTS_TCG_QUALIFIER_TYPE_ALL,
+ PTS_TCG_QUALIFIER_TYPE_TNC,
+ "All Matching Components"
+);
+ENUM_END(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL);
+
+ENUM(pts_tcg_comp_func_names, PTS_TCG_COMP_FUNC_NAME_IGNORE,
+ PTS_TCG_COMP_FUNC_NAME_OPT_ROMS,
+ "Ignore",
+ "CRTM",
+ "BIOS",
+ "Platform Extensions",
+ "Motherboard Firmware",
+ "Initial Program Loader",
+ "Option ROMs"
+);
+
diff --git a/src/libpts/pts/components/tcg/tcg_comp_func_name.h b/src/libpts/pts/components/tcg/tcg_comp_func_name.h
new file mode 100644
index 000000000..9708ad09d
--- /dev/null
+++ b/src/libpts/pts/components/tcg/tcg_comp_func_name.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_tcg_comp_func_name pts_tcg_comp_func_name
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_TCG_COMP_FUNC_NAME_H_
+#define PTS_TCG_COMP_FUNC_NAME_H_
+
+typedef enum pts_tcg_qualifier_type_t pts_tcg_qualifier_type_t;
+typedef enum pts_tcg_comp_func_name_t pts_tcp_comp_func_name_t;
+
+#include <library.h>
+
+/**
+ * PTS Component Functional Name Qualifier Flags for the TCG namespace
+ * see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 0 1 2 3 4 5
+ * +-+-+-+-+-+-+
+ * |K|S| Type |
+ * +-+-+-+-+-+-+
+ */
+#define PTS_TCG_QUALIFIER_FLAG_KERNEL (1<<5)
+#define PTS_TCG_QUALIFIER_FLAG_SUB (1<<4)
+
+extern char pts_tcg_qualifier_flag_names[];
+
+/**
+ * Size of the PTS Component Functional Name Qualifier Type field
+ */
+#define PTS_TCG_QUALIFIER_TYPE_SIZE 4
+
+/**
+ * PTS Component Functional Name Qualifier Types for the TCG namespace
+ * see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_tcg_qualifier_type_t {
+ /** Unknown */
+ PTS_TCG_QUALIFIER_TYPE_UNKNOWN = 0x0,
+ /** Trusted Platform */
+ PTS_TCG_QUALIFIER_TYPE_TRUSTED = 0x1,
+ /** Operating System */
+ PTS_TCG_QUALIFIER_TYPE_OS = 0x2,
+ /** Graphical User Interface */
+ PTS_TCG_QUALIFIER_TYPE_GUI = 0x3,
+ /** Application */
+ PTS_TCG_QUALIFIER_TYPE_APP = 0x4,
+ /** Networking */
+ PTS_TCG_QUALIFIER_TYPE_NET = 0x5,
+ /** Library */
+ PTS_TCG_QUALIFIER_TYPE_LIB = 0x6,
+ /** TNC Defined Component */
+ PTS_TCG_QUALIFIER_TYPE_TNC = 0x7,
+ /** All matching Components */
+ PTS_TCG_QUALIFIER_TYPE_ALL = 0xF,
+};
+
+extern enum_name_t *pts_tcg_qualifier_type_names;
+
+/**
+ * PTS Component Functional Name Binary Enumeration for the TCG namespace
+ * see section 5.3 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_tcg_comp_func_name_t {
+ /** Ignore */
+ PTS_TCG_COMP_FUNC_NAME_IGNORE = 0x0000,
+ /** CRTM */
+ PTS_TCG_COMP_FUNC_NAME_CRTM = 0x0001,
+ /** BIOS */
+ PTS_TCG_COMP_FUNC_NAME_BIOS = 0x0002,
+ /** Platform Extensions */
+ PTS_TCG_COMP_FUNC_NAME_PLATFORM_EXT = 0x0003,
+ /** Motherboard Firmware */
+ PTS_TCG_COMP_FUNC_NAME_BOARD = 0x0004,
+ /** Initial Program Loader */
+ PTS_TCG_COMP_FUNC_NAME_INIT_LOADER = 0x0005,
+ /** Option ROMs */
+ PTS_TCG_COMP_FUNC_NAME_OPT_ROMS = 0x0006,
+};
+
+extern enum_name_t *pts_tcg_comp_func_names;
+
+#endif /** PTS_TCG_COMP_FUNC_NAME_H_ @}*/
diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c
new file mode 100644
index 000000000..65ae2b2d2
--- /dev/null
+++ b/src/libpts/pts/pts.c
@@ -0,0 +1,1539 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts.h"
+
+#include <debug.h>
+#include <crypto/hashers/hasher.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+
+#include <trousers/tss.h>
+#include <trousers/trousers.h>
+
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+#define PTS_BUF_SIZE 4096
+
+/**
+ * Maximum number of PCR's of TPM, TPM Spec 1.2
+ */
+#define PCR_MAX_NUM 24
+
+/**
+ * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
+ */
+#define PCR_LEN 20
+
+typedef struct private_pts_t private_pts_t;
+
+/**
+ * Private data of a pts_t object.
+ *
+ */
+struct private_pts_t {
+
+ /**
+ * Public pts_t interface.
+ */
+ pts_t public;
+
+ /**
+ * PTS Protocol Capabilities
+ */
+ pts_proto_caps_flag_t proto_caps;
+
+ /**
+ * PTS Measurement Algorithm
+ */
+ pts_meas_algorithms_t algorithm;
+
+ /**
+ * DH Hash Algorithm
+ */
+ pts_meas_algorithms_t dh_hash_algorithm;
+
+ /**
+ * PTS Diffie-Hellman Secret
+ */
+ diffie_hellman_t *dh;
+
+ /**
+ * PTS Diffie-Hellman Initiator Nonce
+ */
+ chunk_t initiator_nonce;
+
+ /**
+ * PTS Diffie-Hellman Responder Nonce
+ */
+ chunk_t responder_nonce;
+
+ /**
+ * Secret assessment value to be used for TPM Quote as an external data
+ */
+ chunk_t secret;
+
+ /**
+ * Platform and OS Info
+ */
+ char *platform_info;
+
+ /**
+ * TRUE if IMC-PTS, FALSE if IMV-PTS
+ */
+ bool is_imc;
+
+ /**
+ * Do we have an activated TPM
+ */
+ bool has_tpm;
+
+ /**
+ * Contains a TPM_CAP_VERSION_INFO struct
+ */
+ chunk_t tpm_version_info;
+
+ /**
+ * Contains TSS Blob structure for AIK
+ */
+ chunk_t aik_blob;
+
+ /**
+ * Contains a Attestation Identity Key or Certificate
+ */
+ certificate_t *aik;
+
+ /**
+ * Table of extended PCRs with corresponding values
+ */
+ u_char* pcrs[PCR_MAX_NUM];
+
+ /**
+ * Length of PCR registers
+ */
+ size_t pcr_len;
+
+ /**
+ * Number of extended PCR registers
+ */
+ u_int32_t pcr_count;
+
+ /**
+ * Highest extended PCR register
+ */
+ u_int32_t pcr_max;
+
+ /**
+ * Bitmap of extended PCR registers
+ */
+ u_int8_t pcr_select[PCR_MAX_NUM / 8];
+
+};
+
+METHOD(pts_t, get_proto_caps, pts_proto_caps_flag_t,
+ private_pts_t *this)
+{
+ return this->proto_caps;
+}
+
+METHOD(pts_t, set_proto_caps, void,
+ private_pts_t *this, pts_proto_caps_flag_t flags)
+{
+ this->proto_caps = flags;
+ DBG2(DBG_PTS, "supported PTS protocol capabilities: %s%s%s%s%s",
+ flags & PTS_PROTO_CAPS_C ? "C" : ".",
+ flags & PTS_PROTO_CAPS_V ? "V" : ".",
+ flags & PTS_PROTO_CAPS_D ? "D" : ".",
+ flags & PTS_PROTO_CAPS_T ? "T" : ".",
+ flags & PTS_PROTO_CAPS_X ? "X" : ".");
+}
+
+METHOD(pts_t, get_meas_algorithm, pts_meas_algorithms_t,
+ private_pts_t *this)
+{
+ return this->algorithm;
+}
+
+METHOD(pts_t, set_meas_algorithm, void,
+ private_pts_t *this, pts_meas_algorithms_t algorithm)
+{
+ hash_algorithm_t hash_alg;
+
+ hash_alg = pts_meas_algo_to_hash(algorithm);
+ DBG2(DBG_PTS, "selected PTS measurement algorithm is %N",
+ hash_algorithm_names, hash_alg);
+ if (hash_alg != HASH_UNKNOWN)
+ {
+ this->algorithm = algorithm;
+ }
+}
+
+METHOD(pts_t, get_dh_hash_algorithm, pts_meas_algorithms_t,
+ private_pts_t *this)
+{
+ return this->dh_hash_algorithm;
+}
+
+METHOD(pts_t, set_dh_hash_algorithm, void,
+ private_pts_t *this, pts_meas_algorithms_t algorithm)
+{
+ hash_algorithm_t hash_alg;
+
+ hash_alg = pts_meas_algo_to_hash(algorithm);
+ DBG2(DBG_PTS, "selected DH hash algorithm is %N",
+ hash_algorithm_names, hash_alg);
+ if (hash_alg != HASH_UNKNOWN)
+ {
+ this->dh_hash_algorithm = algorithm;
+ }
+}
+
+
+METHOD(pts_t, create_dh_nonce, bool,
+ private_pts_t *this, pts_dh_group_t group, int nonce_len)
+{
+ diffie_hellman_group_t dh_group;
+ chunk_t *nonce;
+ rng_t *rng;
+
+ dh_group = pts_dh_group_to_ike(group);
+ DBG2(DBG_PTS, "selected PTS DH group is %N",
+ diffie_hellman_group_names, dh_group);
+ DESTROY_IF(this->dh);
+ this->dh = lib->crypto->create_dh(lib->crypto, dh_group);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng)
+ {
+ DBG1(DBG_PTS, "no rng available");
+ return FALSE;
+ }
+ DBG2(DBG_PTS, "nonce length is %d", nonce_len);
+ nonce = this->is_imc ? &this->responder_nonce : &this->initiator_nonce;
+ chunk_free(nonce);
+ rng->allocate_bytes(rng, nonce_len, nonce);
+ rng->destroy(rng);
+
+ return TRUE;
+}
+
+METHOD(pts_t, get_my_public_value, void,
+ private_pts_t *this, chunk_t *value, chunk_t *nonce)
+{
+ this->dh->get_my_public_value(this->dh, value);
+ *nonce = this->is_imc ? this->responder_nonce : this->initiator_nonce;
+}
+
+METHOD(pts_t, set_peer_public_value, void,
+ private_pts_t *this, chunk_t value, chunk_t nonce)
+{
+ this->dh->set_other_public_value(this->dh, value);
+
+ nonce = chunk_clone(nonce);
+ if (this->is_imc)
+ {
+ this->initiator_nonce = nonce;
+ }
+ else
+ {
+ this->responder_nonce = nonce;
+ }
+}
+
+METHOD(pts_t, calculate_secret, bool,
+ private_pts_t *this)
+{
+ hasher_t *hasher;
+ hash_algorithm_t hash_alg;
+ chunk_t shared_secret;
+
+ /* Check presence of nonces */
+ if (!this->initiator_nonce.len || !this->responder_nonce.len)
+ {
+ DBG1(DBG_PTS, "initiator and/or responder nonce is not available");
+ return FALSE;
+ }
+ DBG3(DBG_PTS, "initiator nonce: %B", &this->initiator_nonce);
+ DBG3(DBG_PTS, "responder nonce: %B", &this->responder_nonce);
+
+ /* Calculate the DH secret */
+ if (this->dh->get_shared_secret(this->dh, &shared_secret) != SUCCESS)
+ {
+ DBG1(DBG_PTS, "shared DH secret computation failed");
+ return FALSE;
+ }
+ DBG3(DBG_PTS, "shared DH secret: %B", &shared_secret);
+
+ /* Calculate the secret assessment value */
+ hash_alg = pts_meas_algo_to_hash(this->dh_hash_algorithm);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+
+ hasher->allocate_hash(hasher, chunk_from_chars('1'), NULL);
+ hasher->allocate_hash(hasher, this->initiator_nonce, NULL);
+ hasher->allocate_hash(hasher, this->responder_nonce, NULL);
+ hasher->allocate_hash(hasher, shared_secret, &this->secret);
+ hasher->destroy(hasher);
+
+ /* The DH secret must be destroyed */
+ chunk_clear(&shared_secret);
+
+ /*
+ * Truncate the hash to 20 bytes to fit the ExternalData
+ * argument of the TPM Quote command
+ */
+ this->secret.len = min(this->secret.len, 20);
+ DBG3(DBG_PTS, "secret assessment value: %B", &this->secret);
+ return TRUE;
+}
+
+/**
+ * Print TPM 1.2 Version Info
+ */
+static void print_tpm_version_info(private_pts_t *this)
+{
+ TPM_CAP_VERSION_INFO versionInfo;
+ UINT64 offset = 0;
+ TSS_RESULT result;
+
+ result = Trspi_UnloadBlob_CAP_VERSION_INFO(&offset,
+ this->tpm_version_info.ptr, &versionInfo);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "could not parse tpm version info: tss error 0x%x",
+ result);
+ }
+ else
+ {
+ DBG2(DBG_PTS, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu,"
+ " Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s",
+ versionInfo.version.major, versionInfo.version.minor,
+ versionInfo.version.revMajor, versionInfo.version.revMinor,
+ versionInfo.specLevel, versionInfo.errataRev,
+ versionInfo.tpmVendorID);
+ }
+}
+
+METHOD(pts_t, get_platform_info, char*,
+ private_pts_t *this)
+{
+ return this->platform_info;
+}
+
+METHOD(pts_t, set_platform_info, void,
+ private_pts_t *this, char *info)
+{
+ free(this->platform_info);
+ this->platform_info = strdup(info);
+}
+
+METHOD(pts_t, get_tpm_version_info, bool,
+ private_pts_t *this, chunk_t *info)
+{
+ if (!this->has_tpm)
+ {
+ return FALSE;
+ }
+ *info = this->tpm_version_info;
+ print_tpm_version_info(this);
+ return TRUE;
+}
+
+METHOD(pts_t, set_tpm_version_info, void,
+ private_pts_t *this, chunk_t info)
+{
+ this->tpm_version_info = chunk_clone(info);
+ print_tpm_version_info(this);
+}
+
+METHOD(pts_t, get_pcr_len, size_t,
+ private_pts_t *this)
+{
+ return this->pcr_len;
+}
+
+/**
+ * Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute)
+ */
+static void load_aik_blob(private_pts_t *this)
+{
+ char *blob_path;
+ FILE *fp;
+ u_int32_t aikBlobLen;
+
+ blob_path = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.aik_blob", NULL);
+
+ if (blob_path)
+ {
+ /* Read aik key blob from a file */
+ if ((fp = fopen(blob_path, "r")) == NULL)
+ {
+ DBG1(DBG_PTS, "unable to open AIK Blob file: %s", blob_path);
+ return;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ aikBlobLen = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ this->aik_blob = chunk_alloc(aikBlobLen);
+ if (fread(this->aik_blob.ptr, 1, aikBlobLen, fp))
+ {
+ DBG2(DBG_PTS, "loaded AIK Blob from '%s'", blob_path);
+ DBG3(DBG_PTS, "AIK Blob: %B", &this->aik_blob);
+ }
+ else
+ {
+ DBG1(DBG_PTS, "unable to read AIK Blob file '%s'", blob_path);
+ }
+ fclose(fp);
+ return;
+ }
+
+ DBG1(DBG_PTS, "AIK Blob is not available");
+}
+
+/**
+ * Load an AIK certificate or public key
+ * the certificate having precedence over the public key if both are present
+ */
+static void load_aik(private_pts_t *this)
+{
+ char *cert_path, *key_path;
+
+ cert_path = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.aik_cert", NULL);
+ key_path = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imc-attestation.aik_key", NULL);
+
+ if (cert_path)
+ {
+ this->aik = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_FROM_FILE,
+ cert_path, BUILD_END);
+ if (this->aik)
+ {
+ DBG2(DBG_PTS, "loaded AIK certificate from '%s'", cert_path);
+ return;
+ }
+ }
+ if (key_path)
+ {
+ this->aik = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
+ key_path, BUILD_END);
+ if (this->aik)
+ {
+ DBG2(DBG_PTS, "loaded AIK public key from '%s'", key_path);
+ return;
+ }
+ }
+
+ DBG1(DBG_PTS, "neither AIK certificate nor public key is available");
+}
+
+METHOD(pts_t, get_aik, certificate_t*,
+ private_pts_t *this)
+{
+ return this->aik;
+}
+
+METHOD(pts_t, set_aik, void,
+ private_pts_t *this, certificate_t *aik)
+{
+ DESTROY_IF(this->aik);
+ this->aik = aik->get_ref(aik);
+}
+
+METHOD(pts_t, get_aik_keyid, bool,
+ private_pts_t *this, chunk_t *keyid)
+{
+ public_key_t *public;
+ bool success;
+
+ if (!this->aik)
+ {
+ DBG1(DBG_PTS, "no AIK certificate available");
+ return FALSE;
+ }
+ public = this->aik->get_public_key(this->aik);
+ if (!public)
+ {
+ DBG1(DBG_PTS, "no AIK public key available");
+ return FALSE;
+ }
+ success = public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, keyid);
+ if (!success)
+ {
+ DBG1(DBG_PTS, "no SHA-1 AIK public key info ID available");
+ }
+ public->destroy(public);
+
+ return success;
+}
+
+METHOD(pts_t, hash_file, bool,
+ private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
+{
+ u_char buffer[PTS_BUF_SIZE];
+ FILE *file;
+ int bytes_read;
+
+ file = fopen(pathname, "rb");
+ if (!file)
+ {
+ DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ return FALSE;
+ }
+ while (TRUE)
+ {
+ bytes_read = fread(buffer, 1, sizeof(buffer), file);
+ if (bytes_read > 0)
+ {
+ hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
+ }
+ else
+ {
+ hasher->get_hash(hasher, chunk_empty, hash);
+ break;
+ }
+ }
+ fclose(file);
+
+ return TRUE;
+}
+
+/**
+ * Get the relative filename of a fully qualified file pathname
+ */
+static char* get_filename(char *pathname)
+{
+ char *pos, *filename;
+
+ pos = filename = pathname;
+ while (pos && *(++pos) != '\0')
+ {
+ filename = pos;
+ pos = strchr(filename, '/');
+ }
+ return filename;
+}
+
+METHOD(pts_t, is_path_valid, bool,
+ private_pts_t *this, char *path, pts_error_code_t *error_code)
+{
+ struct stat st;
+
+ *error_code = 0;
+
+ if (!stat(path, &st))
+ {
+ return TRUE;
+ }
+ else if (errno == ENOENT || errno == ENOTDIR)
+ {
+ DBG1(DBG_PTS, "file/directory does not exist %s", path);
+ *error_code = TCG_PTS_FILE_NOT_FOUND;
+ }
+ else if (errno == EFAULT)
+ {
+ DBG1(DBG_PTS, "bad address %s", path);
+ *error_code = TCG_PTS_INVALID_PATH;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "error: %s occurred while validating path: %s",
+ strerror(errno), path);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+METHOD(pts_t, do_measurements, pts_file_meas_t*,
+ private_pts_t *this, u_int16_t request_id, char *pathname, bool is_directory)
+{
+ hasher_t *hasher;
+ hash_algorithm_t hash_alg;
+ u_char hash[HASH_SIZE_SHA384];
+ chunk_t measurement;
+ pts_file_meas_t *measurements;
+
+ /* Create a hasher */
+ hash_alg = pts_meas_algo_to_hash(this->algorithm);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+ if (!hasher)
+ {
+ DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
+ return NULL;
+ }
+
+ /* Create a measurement object */
+ measurements = pts_file_meas_create(request_id);
+
+ /* Link the hash to the measurement and set the measurement length */
+ measurement = chunk_create(hash, hasher->get_hash_size(hasher));
+
+ if (is_directory)
+ {
+ enumerator_t *enumerator;
+ char *rel_name, *abs_name;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ hasher->destroy(hasher);
+ measurements->destroy(measurements);
+ return NULL;
+ }
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ /* measure regular files only */
+ if (S_ISREG(st.st_mode) && *rel_name != '.')
+ {
+ if (!hash_file(this, hasher, abs_name, hash))
+ {
+ enumerator->destroy(enumerator);
+ hasher->destroy(hasher);
+ measurements->destroy(measurements);
+ return NULL;
+ }
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, rel_name);
+ measurements->add(measurements, rel_name, measurement);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ char *filename;
+
+ if (!hash_file(this, hasher, pathname, hash))
+ {
+ hasher->destroy(hasher);
+ measurements->destroy(measurements);
+ return NULL;
+ }
+ filename = get_filename(pathname);
+ DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
+ measurements->add(measurements, filename, measurement);
+ }
+ hasher->destroy(hasher);
+
+ return measurements;
+}
+
+/**
+ * Obtain statistical information describing a file
+ */
+static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
+{
+ struct stat st;
+ pts_file_metadata_t *this;
+
+ this = malloc_thing(pts_file_metadata_t);
+
+ if (stat(pathname, &st))
+ {
+ DBG1(DBG_PTS, "unable to obtain statistics about '%s'", pathname);
+ return FALSE;
+ }
+
+ if (S_ISREG(st.st_mode))
+ {
+ this->type = PTS_FILE_REGULAR;
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ this->type = PTS_FILE_DIRECTORY;
+ }
+ else if (S_ISCHR(st.st_mode))
+ {
+ this->type = PTS_FILE_CHAR_SPEC;
+ }
+ else if (S_ISBLK(st.st_mode))
+ {
+ this->type = PTS_FILE_BLOCK_SPEC;
+ }
+ else if (S_ISFIFO(st.st_mode))
+ {
+ this->type = PTS_FILE_FIFO;
+ }
+ else if (S_ISLNK(st.st_mode))
+ {
+ this->type = PTS_FILE_SYM_LINK;
+ }
+ else if (S_ISSOCK(st.st_mode))
+ {
+ this->type = PTS_FILE_SOCKET;
+ }
+ else
+ {
+ this->type = PTS_FILE_OTHER;
+ }
+
+ this->filesize = st.st_size;
+ this->created = st.st_ctime;
+ this->modified = st.st_mtime;
+ this->accessed = st.st_atime;
+ this->owner = st.st_uid;
+ this->group = st.st_gid;
+
+ *entry = this;
+ return TRUE;
+}
+
+METHOD(pts_t, get_metadata, pts_file_meta_t*,
+ private_pts_t *this, char *pathname, bool is_directory)
+{
+ pts_file_meta_t *metadata;
+ pts_file_metadata_t *entry;
+
+ /* Create a metadata object */
+ metadata = pts_file_meta_create();
+
+ if (is_directory)
+ {
+ enumerator_t *enumerator;
+ char *rel_name, *abs_name;
+ struct stat st;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
+ strerror(errno));
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ /* measure regular files only */
+ if (S_ISREG(st.st_mode) && *rel_name != '.')
+ {
+ if (!file_metadata(abs_name, &entry))
+ {
+ enumerator->destroy(enumerator);
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ entry->filename = strdup(rel_name);
+ metadata->add(metadata, entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ if (!file_metadata(pathname, &entry))
+ {
+ metadata->destroy(metadata);
+ return NULL;
+ }
+ entry->filename = strdup(get_filename(pathname));
+ metadata->add(metadata, entry);
+ }
+
+ return metadata;
+}
+
+METHOD(pts_t, read_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ chunk_t rgbPcrValue;
+
+ bool success = FALSE;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x", result);
+ return FALSE;
+ }
+
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_TPM_PcrRead(hTPM, pcr_num, (UINT32*)&rgbPcrValue.len, &rgbPcrValue.ptr);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ *pcr_value = chunk_clone(rgbPcrValue);
+ DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, pcr_value);
+ success = TRUE;
+
+err:
+ if (!success)
+ {
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ }
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return success;
+}
+
+METHOD(pts_t, extend_pcr, bool,
+ private_pts_t *this, u_int32_t pcr_num, chunk_t input, chunk_t *output)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ u_int32_t pcr_length;
+ chunk_t pcr_value;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+
+ pcr_value = chunk_alloc(PCR_LEN);
+ result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr,
+ NULL, &pcr_length, &pcr_value.ptr);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+
+ *output = pcr_value;
+ *output = chunk_clone(*output);
+
+ DBG3(DBG_PTS, "PCR %d extended with: %B", pcr_num, &input);
+ DBG3(DBG_PTS, "PCR %d value after extend: %B", pcr_num, output);
+
+ chunk_clear(&pcr_value);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return TRUE;
+
+err:
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+
+ chunk_clear(&pcr_value);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+
+ return FALSE;
+}
+
+
+static void clear_pcrs(private_pts_t *this)
+{
+ int i;
+
+ for (i = 0; i <= this->pcr_max; i++)
+ {
+ free(this->pcrs[i]);
+ this->pcrs[i] = NULL;
+ }
+ this->pcr_count = 0;
+ this->pcr_max = 0;
+
+ memset(this->pcr_select, 0x00, sizeof(this->pcr_select));
+}
+
+METHOD(pts_t, quote_tpm, bool,
+ private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_HKEY hAIK;
+ TSS_HKEY hSRK;
+ TSS_HPOLICY srkUsagePolicy;
+ TSS_UUID SRK_UUID = TSS_UUID_SRK;
+ BYTE secret[] = TSS_WELL_KNOWN_SECRET;
+ TSS_HPCRS hPcrComposite;
+ TSS_VALIDATION valData;
+ TSS_RESULT result;
+ chunk_t quote_info;
+ BYTE* versionInfo;
+ u_int32_t versionInfoSize, pcr, i = 0, f = 1;
+ bool success = FALSE;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ /* Retrieve SRK from TPM and set the authentication to well known secret*/
+ result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
+ SRK_UUID, &hSRK);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+ result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1,
+ 20, secret);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ result = Tspi_Context_LoadKeyByBlob (hContext, hSRK, this->aik_blob.len,
+ this->aik_blob.ptr, &hAIK);
+ if (result != TSS_SUCCESS)
+ {
+ goto err1;
+ }
+
+ /* Create PCR composite object */
+ result = use_quote2 ?
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ TSS_PCRS_STRUCT_INFO_SHORT, &hPcrComposite) :
+ Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+ 0, &hPcrComposite);
+ if (result != TSS_SUCCESS)
+ {
+ goto err2;
+ }
+
+ /* Select PCRs */
+ for (pcr = 0; pcr <= this->pcr_max ; pcr++)
+ {
+ if (f == 256)
+ {
+ i++;
+ f = 1;
+ }
+ if (this->pcr_select[i] & f)
+ {
+ result = use_quote2 ?
+ Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
+ TSS_PCRS_DIRECTION_RELEASE) :
+ Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
+ if (result != TSS_SUCCESS)
+ {
+ goto err3;
+ }
+ }
+ f <<= 1;
+ }
+
+ /* Set the Validation Data */
+ valData.ulExternalDataLength = this->secret.len;
+ valData.rgbExternalData = (BYTE *)this->secret.ptr;
+
+
+ /* TPM Quote */
+ result = use_quote2 ?
+ Tspi_TPM_Quote2(hTPM, hAIK, FALSE, hPcrComposite, &valData,
+ &versionInfoSize, &versionInfo):
+ Tspi_TPM_Quote(hTPM, hAIK, hPcrComposite, &valData);
+ if (result != TSS_SUCCESS)
+ {
+ goto err4;
+ }
+
+ /* Set output chunks */
+ *pcr_comp = chunk_alloc(HASH_SIZE_SHA1);
+
+ if (use_quote2)
+ {
+ /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
+ memcpy(pcr_comp->ptr, valData.rgbData + valData.ulDataLength - HASH_SIZE_SHA1,
+ HASH_SIZE_SHA1);
+ }
+ else
+ {
+ /* TPM_Composite_Hash is 8-28th bytes of TPM_Quote_Info structure */
+ memcpy(pcr_comp->ptr, valData.rgbData + 8, HASH_SIZE_SHA1);
+ }
+ DBG3(DBG_PTS, "Hash of PCR Composite: %#B", pcr_comp);
+
+ quote_info = chunk_create(valData.rgbData, valData.ulDataLength);
+ DBG3(DBG_PTS, "TPM Quote Info: %B",&quote_info);
+
+ *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData,
+ valData.ulValidationDataLength));
+ DBG3(DBG_PTS, "TPM Quote Signature: %B",quote_sig);
+
+ success = TRUE;
+
+ /* Cleanup */
+err4:
+ Tspi_Context_FreeMemory(hContext, NULL);
+
+err3:
+ Tspi_Context_CloseObject(hContext, hPcrComposite);
+
+err2:
+ Tspi_Context_CloseObject(hContext, hAIK);
+
+err1:
+ Tspi_Context_Close(hContext);
+
+ if (!success)
+ {
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ }
+ clear_pcrs(this);
+
+ return success;
+}
+
+METHOD(pts_t, select_pcr, bool,
+ private_pts_t *this, u_int32_t pcr)
+{
+ u_int32_t i, f;
+
+ if (pcr >= PCR_MAX_NUM)
+ {
+ DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
+ pcr, PCR_MAX_NUM-1);
+ return FALSE;
+ }
+
+ /* Determine PCR selection flag */
+ i = pcr / 8;
+ f = 1 << (pcr - 8*i);
+
+ /* Has this PCR already been selected? */
+ if (!(this->pcr_select[i] & f))
+ {
+ this->pcr_select[i] |= f;
+ this->pcr_max = max(this->pcr_max, pcr);
+ this->pcr_count++;
+ }
+
+ return TRUE;
+}
+
+METHOD(pts_t, add_pcr, bool,
+ private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after)
+{
+ if (pcr >= PCR_MAX_NUM)
+ {
+ DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
+ pcr, PCR_MAX_NUM-1);
+ return FALSE;
+ }
+
+ /* Is the length of the PCR registers already set? */
+ if (this->pcr_len)
+ {
+ if (pcr_after.len != this->pcr_len)
+ {
+ DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes",
+ pcr_after.len, this->pcr_len);
+ return FALSE;
+ }
+ }
+ else
+ {
+ this->pcr_len = pcr_after.len;
+ }
+
+ /* Has the value of the PCR register already been assigned? */
+ if (this->pcrs[pcr])
+ {
+ if (!memeq(this->pcrs[pcr], pcr_before.ptr, this->pcr_len))
+ {
+ DBG1(DBG_PTS, "PCR %02u: new pcr_before value does not equal "
+ "old pcr_after value");
+ }
+ /* remove the old PCR value */
+ free(this->pcrs[pcr]);
+ }
+ else
+ {
+ /* add extended PCR Register */
+ this->pcr_select[pcr / 8] |= 1 << (pcr % 8);
+ this->pcr_max = max(this->pcr_max, pcr);
+ this->pcr_count++;
+ }
+
+ /* Duplicate and store current PCR value */
+ pcr_after = chunk_clone(pcr_after);
+ this->pcrs[pcr] = pcr_after.ptr;
+
+ return TRUE;
+}
+
+/**
+ * TPM_QUOTE_INFO structure:
+ * 4 bytes of version
+ * 4 bytes 'Q' 'U' 'O' 'T'
+ * 20 byte SHA1 of TCPA_PCR_COMPOSITE
+ * 20 byte nonce
+ *
+ * TPM_QUOTE_INFO2 structure:
+ * 2 bytes Tag 0x0036 TPM_Tag_Quote_info2
+ * 4 bytes 'Q' 'U' 'T' '2'
+ * 20 bytes nonce
+ * 26 bytes PCR_INFO_SHORT
+ */
+
+METHOD(pts_t, get_quote_info, bool,
+ private_pts_t *this, bool use_quote2, bool use_ver_info,
+ pts_meas_algorithms_t comp_hash_algo,
+ chunk_t *out_pcr_comp, chunk_t *out_quote_info)
+{
+ u_int8_t size_of_select;
+ int pcr_comp_len, i;
+ chunk_t pcr_comp, hash_pcr_comp;
+ bio_writer_t *writer;
+ hasher_t *hasher;
+
+ if (this->pcr_count == 0)
+ {
+ DBG1(DBG_PTS, "No extended PCR entries available, "
+ "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+ if (!this->secret.ptr)
+ {
+ DBG1(DBG_PTS, "Secret assessment value unavailable, ",
+ "unable to construct TPM Quote Info");
+ return FALSE;
+ }
+ if (use_quote2 && use_ver_info && !this->tpm_version_info.ptr)
+ {
+ DBG1(DBG_PTS, "TPM Version Information unavailable, ",
+ "unable to construct TPM Quote Info2");
+ return FALSE;
+ }
+
+ /**
+ * A TPM v1.2 has 24 PCR Registers
+ * so the bitmask field length used by TrouSerS is at least 3 bytes
+ */
+ size_of_select = max(PCR_MAX_NUM / 8, 1 + this->pcr_max / 8);
+ pcr_comp_len = 2 + size_of_select + 4 + this->pcr_count * this->pcr_len;
+
+ writer = bio_writer_create(pcr_comp_len);
+
+ writer->write_uint16(writer, size_of_select);
+ for (i = 0; i < size_of_select; i++)
+ {
+ writer->write_uint8(writer, this->pcr_select[i]);
+ }
+
+ writer->write_uint32(writer, this->pcr_count * this->pcr_len);
+ for (i = 0; i < 8 * size_of_select; i++)
+ {
+ if (this->pcrs[i])
+ {
+ writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len));
+ }
+ }
+ pcr_comp = chunk_clone(writer->get_buf(writer));
+ DBG3(DBG_PTS, "constructed PCR Composite: %B", &pcr_comp);
+
+ writer->destroy(writer);
+
+ /* Output the TPM_PCR_COMPOSITE expected from IMC */
+ if (comp_hash_algo)
+ {
+ hash_algorithm_t algo;
+
+ algo = pts_meas_algo_to_hash(comp_hash_algo);
+ hasher = lib->crypto->create_hasher(lib->crypto, algo);
+
+ /* Hash the PCR Composite Structure */
+ hasher->allocate_hash(hasher, pcr_comp, out_pcr_comp);
+ DBG3(DBG_PTS, "constructed PCR Composite hash: %#B", out_pcr_comp);
+ hasher->destroy(hasher);
+ }
+ else
+ {
+ *out_pcr_comp = chunk_clone(pcr_comp);
+ }
+
+ /* SHA1 hash of PCR Composite to construct TPM_QUOTE_INFO */
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ hasher->allocate_hash(hasher, pcr_comp, &hash_pcr_comp);
+ hasher->destroy(hasher);
+
+ /* Construct TPM_QUOTE_INFO/TPM_QUOTE_INFO2 structure */
+ writer = bio_writer_create(TPM_QUOTE_INFO_LEN);
+
+ if (use_quote2)
+ {
+ /* TPM Structure Tag */
+ writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2);
+
+ /* Magic QUT2 value */
+ writer->write_data(writer, chunk_create("QUT2", 4));
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
+
+ /* Length of the PCR selection field */
+ writer->write_uint16(writer, size_of_select);
+
+ /* PCR selection */
+ for (i = 0; i < size_of_select ; i++)
+ {
+ writer->write_uint8(writer, this->pcr_select[i]);
+ }
+
+ /* TPM Locality Selection */
+ writer->write_uint8(writer, TPM_LOC_ZERO);
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_comp);
+
+ if (use_ver_info)
+ {
+ /* TPM version Info */
+ writer->write_data(writer, this->tpm_version_info);
+ }
+ }
+ else
+ {
+ /* Version number */
+ writer->write_data(writer, chunk_from_chars(1, 1, 0, 0));
+
+ /* Magic QUOT value */
+ writer->write_data(writer, chunk_create("QUOT", 4));
+
+ /* PCR Composite Hash */
+ writer->write_data(writer, hash_pcr_comp);
+
+ /* Secret assessment value 20 bytes (nonce) */
+ writer->write_data(writer, this->secret);
+ }
+
+ /* TPM Quote Info */
+ *out_quote_info = chunk_clone(writer->get_buf(writer));
+ DBG3(DBG_PTS, "constructed TPM Quote Info: %B", out_quote_info);
+
+ writer->destroy(writer);
+ free(pcr_comp.ptr);
+ free(hash_pcr_comp.ptr);
+ clear_pcrs(this);
+
+ return TRUE;
+}
+
+METHOD(pts_t, verify_quote_signature, bool,
+ private_pts_t *this, chunk_t data, chunk_t signature)
+{
+ public_key_t *aik_pub_key;
+
+ aik_pub_key = this->aik->get_public_key(this->aik);
+ if (!aik_pub_key)
+ {
+ DBG1(DBG_PTS, "failed to get public key from AIK certificate");
+ return FALSE;
+ }
+
+ if (!aik_pub_key->verify(aik_pub_key, SIGN_RSA_EMSA_PKCS1_SHA1,
+ data, signature))
+ {
+ DBG1(DBG_PTS, "signature verification failed for TPM Quote Info");
+ DESTROY_IF(aik_pub_key);
+ return FALSE;
+ }
+
+ aik_pub_key->destroy(aik_pub_key);
+ return TRUE;
+}
+
+METHOD(pts_t, destroy, void,
+ private_pts_t *this)
+{
+ clear_pcrs(this);
+ DESTROY_IF(this->aik);
+ DESTROY_IF(this->dh);
+ free(this->initiator_nonce.ptr);
+ free(this->responder_nonce.ptr);
+ free(this->secret.ptr);
+ free(this->platform_info);
+ free(this->aik_blob.ptr);
+ free(this->tpm_version_info.ptr);
+ free(this);
+}
+
+#define RELEASE_LSB 0
+#define RELEASE_DEBIAN 1
+
+/**
+ * Determine Linux distribution and hardware platform
+ */
+static char* extract_platform_info(void)
+{
+ FILE *file;
+ char buf[BUF_LEN], *pos = buf, *value = NULL;
+ int i, len = BUF_LEN - 1;
+ struct utsname uninfo;
+
+ /* Linux/Unix distribution release info (from http://linuxmafia.com) */
+ const char* releases[] = {
+ "/etc/lsb-release", "/etc/debian_version",
+ "/etc/SuSE-release", "/etc/novell-release",
+ "/etc/sles-release", "/etc/redhat-release",
+ "/etc/fedora-release", "/etc/gentoo-release",
+ "/etc/slackware-version", "/etc/annvix-release",
+ "/etc/arch-release", "/etc/arklinux-release",
+ "/etc/aurox-release", "/etc/blackcat-release",
+ "/etc/cobalt-release", "/etc/conectiva-release",
+ "/etc/debian_release", "/etc/immunix-release",
+ "/etc/lfs-release", "/etc/linuxppc-release",
+ "/etc/mandrake-release", "/etc/mandriva-release",
+ "/etc/mandrakelinux-release", "/etc/mklinux-release",
+ "/etc/pld-release", "/etc/redhat_version",
+ "/etc/slackware-release", "/etc/e-smith-release",
+ "/etc/release", "/etc/sun-release",
+ "/etc/tinysofa-release", "/etc/turbolinux-release",
+ "/etc/ultrapenguin-release", "/etc/UnitedLinux-release",
+ "/etc/va-release", "/etc/yellowdog-release"
+ };
+
+ const char description[] = "DISTRIB_DESCRIPTION=\"";
+ const char str_debian[] = "Debian ";
+
+ for (i = 0; i < countof(releases); i++)
+ {
+ file = fopen(releases[i], "r");
+ if (!file)
+ {
+ continue;
+ }
+
+ if (i == RELEASE_DEBIAN)
+ {
+ strcpy(buf, str_debian);
+ pos += strlen(str_debian);
+ len -= strlen(str_debian);
+ }
+
+ fseek(file, 0, SEEK_END);
+ len = min(ftell(file), len);
+ rewind(file);
+ pos[len] = '\0';
+ if (fread(pos, 1, len, file) != len)
+ {
+ DBG1(DBG_PTS, "failed to read file '%s'", releases[i]);
+ fclose(file);
+ return NULL;
+ }
+ fclose(file);
+
+ if (i == RELEASE_LSB)
+ {
+ pos = strstr(buf, description);
+ if (!pos)
+ {
+ DBG1(DBG_PTS, "failed to find begin of lsb-release "
+ "DESCRIPTION field");
+ return NULL;
+ }
+ value = pos + strlen(description);
+ pos = strchr(value, '"');
+ if (!pos)
+ {
+ DBG1(DBG_PTS, "failed to find end of lsb-release "
+ "DESCRIPTION field");
+ return NULL;
+ }
+ }
+ else
+ {
+ value = buf;
+ pos = strchr(pos, '\n');
+ if (!pos)
+ {
+ DBG1(DBG_PTS, "failed to find end of release string");
+ return NULL;
+ }
+ }
+ break;
+ }
+
+ if (!value)
+ {
+ DBG1(DBG_PTS, "no distribution release file found");
+ return NULL;
+ }
+
+ if (uname(&uninfo) < 0)
+ {
+ DBG1(DBG_PTS, "could not retrieve machine architecture");
+ return NULL;
+ }
+
+ *pos++ = ' ';
+ len = sizeof(buf)-1 + (pos - buf);
+ strncpy(pos, uninfo.machine, len);
+
+ DBG1(DBG_PTS, "platform is '%s'", value);
+ return strdup(value);
+}
+
+/**
+ * Check for a TPM by querying for TPM Version Info
+ */
+static bool has_tpm(private_pts_t *this)
+{
+ TSS_HCONTEXT hContext;
+ TSS_HTPM hTPM;
+ TSS_RESULT result;
+ u_int32_t version_info_len;
+
+ result = Tspi_Context_Create(&hContext);
+ if (result != TSS_SUCCESS)
+ {
+ DBG1(DBG_PTS, "TPM context could not be created: tss error 0x%x",
+ result);
+ return FALSE;
+ }
+ result = Tspi_Context_Connect(hContext, NULL);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ result = Tspi_TPM_GetCapability(hTPM, TSS_TPMCAP_VERSION_VAL, 0, NULL,
+ &version_info_len,
+ &this->tpm_version_info.ptr);
+ this->tpm_version_info.len = version_info_len;
+ if (result != TSS_SUCCESS)
+ {
+ goto err;
+ }
+ this->tpm_version_info = chunk_clone(this->tpm_version_info);
+
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+ return TRUE;
+
+ err:
+ DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
+ Tspi_Context_FreeMemory(hContext, NULL);
+ Tspi_Context_Close(hContext);
+ return FALSE;
+}
+
+/**
+ * See header
+ */
+pts_t *pts_create(bool is_imc)
+{
+ private_pts_t *this;
+
+ INIT(this,
+ .public = {
+ .get_proto_caps = _get_proto_caps,
+ .set_proto_caps = _set_proto_caps,
+ .get_meas_algorithm = _get_meas_algorithm,
+ .set_meas_algorithm = _set_meas_algorithm,
+ .get_dh_hash_algorithm = _get_dh_hash_algorithm,
+ .set_dh_hash_algorithm = _set_dh_hash_algorithm,
+ .create_dh_nonce = _create_dh_nonce,
+ .get_my_public_value = _get_my_public_value,
+ .set_peer_public_value = _set_peer_public_value,
+ .calculate_secret = _calculate_secret,
+ .get_platform_info = _get_platform_info,
+ .set_platform_info = _set_platform_info,
+ .get_tpm_version_info = _get_tpm_version_info,
+ .set_tpm_version_info = _set_tpm_version_info,
+ .get_pcr_len = _get_pcr_len,
+ .get_aik = _get_aik,
+ .set_aik = _set_aik,
+ .get_aik_keyid = _get_aik_keyid,
+ .is_path_valid = _is_path_valid,
+ .hash_file = _hash_file,
+ .do_measurements = _do_measurements,
+ .get_metadata = _get_metadata,
+ .read_pcr = _read_pcr,
+ .extend_pcr = _extend_pcr,
+ .quote_tpm = _quote_tpm,
+ .select_pcr = _select_pcr,
+ .add_pcr = _add_pcr,
+ .get_quote_info = _get_quote_info,
+ .verify_quote_signature = _verify_quote_signature,
+ .destroy = _destroy,
+ },
+ .is_imc = is_imc,
+ .proto_caps = PTS_PROTO_CAPS_V,
+ .algorithm = PTS_MEAS_ALGO_SHA256,
+ .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+ );
+
+ if (is_imc)
+ {
+ this->platform_info = extract_platform_info();
+
+ if (has_tpm(this))
+ {
+ this->has_tpm = TRUE;
+ this->pcr_len = PCR_LEN;
+ this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
+ load_aik(this);
+ load_aik_blob(this);
+ }
+ }
+ else
+ {
+ this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
+ }
+
+ return &this->public;
+}
diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h
new file mode 100644
index 000000000..212acb02a
--- /dev/null
+++ b/src/libpts/pts/pts.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts pts
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_H_
+#define PTS_H_
+
+typedef struct pts_t pts_t;
+
+#include "pts_error.h"
+#include "pts_proto_caps.h"
+#include "pts_meas_algo.h"
+#include "pts_file_meas.h"
+#include "pts_file_meta.h"
+#include "pts_dh_group.h"
+#include "pts_req_func_comp_evid.h"
+#include "pts_simple_evid_final.h"
+#include "components/pts_comp_func_name.h"
+
+#include <library.h>
+#include <utils/linked_list.h>
+
+/**
+ * UTF-8 encoding of the character used to delimiter the filename
+ */
+#define SOLIDUS_UTF 0x2F
+#define REVERSE_SOLIDUS_UTF 0x5C
+
+/**
+ * PCR indices used for measurements of various functional components
+ */
+#define PCR_BIOS 0
+#define PCR_PLATFORM_EXT 1
+#define PCR_MOTHERBOARD 1
+#define PCR_OPTION_ROMS 2
+#define PCR_IPL 4
+
+#define PCR_TBOOT_POLICY 17
+#define PCR_TBOOT_MLE 18
+
+#define PCR_TGRUB_MBR_STAGE1 4
+#define PCR_TGRUB_STAGE2_PART1 8
+#define PCR_TGRUB_STAGE2_PART2 9
+#define PCR_TGRUB_CMD_LINE_ARGS 12
+#define PCR_TGRUB_CHECKFILE 13
+#define PCR_TGRUB_LOADED_FILES 14
+
+#define PCR_DEBUG 16
+
+/**
+ * Length of the generated nonce used for calculation of shared secret
+ */
+#define ASSESSMENT_SECRET_LEN 20
+
+/**
+ * Length of the TPM_QUOTE_INFO structure, TPM Spec 1.2
+ */
+#define TPM_QUOTE_INFO_LEN 48
+
+/**
+ * Hashing algorithm used by tboot and trustedGRUB
+ */
+#define TRUSTED_HASH_ALGO PTS_MEAS_ALGO_SHA1
+
+/**
+ * Class implementing the TCG Platform Trust Service (PTS)
+ *
+ */
+struct pts_t {
+
+ /**
+ * Get PTS Protocol Capabilities
+ *
+ * @return Protocol capabilities flags
+ */
+ pts_proto_caps_flag_t (*get_proto_caps)(pts_t *this);
+
+ /**
+ * Set PTS Protocol Capabilities
+ *
+ * @param flags Protocol capabilities flags
+ */
+ void (*set_proto_caps)(pts_t *this, pts_proto_caps_flag_t flags);
+
+ /**
+ * Get PTS Measurement Algorithm
+ *
+ * @return PTS measurement algorithm
+ */
+ pts_meas_algorithms_t (*get_meas_algorithm)(pts_t *this);
+
+ /**
+ * Set PTS Measurement Algorithm
+ *
+ * @param algorithm PTS measurement algorithm
+ */
+ void (*set_meas_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
+
+ /**
+ * Get DH Hash Algorithm
+ *
+ * @return DH hash algorithm
+ */
+ pts_meas_algorithms_t (*get_dh_hash_algorithm)(pts_t *this);
+
+ /**
+ * Set DH Hash Algorithm
+ *
+ * @param algorithm DH hash algorithm
+ */
+ void (*set_dh_hash_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
+
+ /**
+ * Create PTS Diffie-Hellman object and nonce
+ *
+ * @param group PTS DH group
+ * @param nonce_len Nonce length
+ * @return TRUE if creation was successful
+ *
+ */
+ bool (*create_dh_nonce)(pts_t *this, pts_dh_group_t group, int nonce_len);
+
+ /**
+ * Get my Diffie-Hellman public value
+ *
+ * @param value My public DH value
+ * @param nonce My DH nonce
+ */
+ void (*get_my_public_value)(pts_t *this, chunk_t *value, chunk_t *nonce);
+
+ /**
+ * Set peer Diffie.Hellman public value
+ *
+ * @param value Peer public DH value
+ * @param nonce Peer DH nonce
+ */
+ void (*set_peer_public_value) (pts_t *this, chunk_t value, chunk_t nonce);
+
+ /**
+ * Calculates assessment secret to be used for TPM Quote as ExternalData
+ *
+ * @return TRUE unless both DH public values
+ * and nonces are set
+ */
+ bool (*calculate_secret) (pts_t *this);
+
+ /**
+ * Get Platform and OS Info
+ *
+ * @return Platform and OS info
+ */
+ char* (*get_platform_info)(pts_t *this);
+
+ /**
+ * Set Platform and OS Info
+ *
+ * @param info Platform and OS info
+ */
+ void (*set_platform_info)(pts_t *this, char *info);
+
+ /**
+ * Get TPM 1.2 Version Info
+ *
+ * @param info chunk containing a TPM_CAP_VERSION_INFO struct
+ * @return TRUE if TPM Version Info available
+ */
+ bool (*get_tpm_version_info)(pts_t *this, chunk_t *info);
+
+ /**
+ * Set TPM 1.2 Version Info
+ *
+ * @param info chunk containing a TPM_CAP_VERSION_INFO struct
+ */
+ void (*set_tpm_version_info)(pts_t *this, chunk_t info);
+
+ /**
+ * Get the length of the TPM PCR registers
+ *
+ * @return Length of PCR registers in bytes, 0 if undefined
+ */
+ size_t (*get_pcr_len)(pts_t *this);
+
+ /**
+ * Get Attestation Identity Certificate or Public Key
+ *
+ * @return AIK Certificate or Public Key
+ */
+ certificate_t* (*get_aik)(pts_t *this);
+
+ /**
+ * Set Attestation Identity Certificate or Public Key
+ *
+ * @param aik AIK Certificate or Public Key
+ */
+ void (*set_aik)(pts_t *this, certificate_t *aik);
+
+ /**
+ * Get SHA-1 Attestation Identity Public Key Info ID
+ *
+ * @param keyid AIK ID
+ * @return TRUE if AIK ID exists
+ */
+ bool (*get_aik_keyid)(pts_t *this, chunk_t *keyid);
+
+ /**
+ * Check whether path is valid file/directory on filesystem
+ *
+ * @param path Absolute path
+ * @param error_code Output variable for PTS error code
+ * @return TRUE if path is valid or file/directory
+ * doesn't exist or path is invalid
+ * FALSE if local error occurred within stat function
+ */
+ bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
+
+ /**
+ * Compute a hash over a file
+ * @param hasher Hasher to be used
+ * @param pathname Absolute path of a file
+ * @param hash Buffer to keep hash output
+ * @return TRUE if path is valid and hashing succeeded
+ */
+ bool (*hash_file)(pts_t *this, hasher_t *hasher, char *pathname, u_char *hash);
+
+ /**
+ * Do PTS File Measurements
+ *
+ * @param request_id ID of PTS File Measurement Request
+ * @param pathname Absolute pathname of file to be measured
+ * @param is_directory TRUE if directory contents are measured
+ * @return PTS File Measurements of NULL if FAILED
+ */
+ pts_file_meas_t* (*do_measurements)(pts_t *this, u_int16_t request_id,
+ char *pathname, bool is_directory);
+
+ /**
+ * Obtain file metadata
+ *
+ * @param pathname Absolute pathname of file/directory
+ * @param is_directory TRUE if directory contents are requested
+ * @return PTS File Metadata or NULL if FAILED
+ */
+ pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname,
+ bool is_directory);
+
+ /**
+ * Reads given PCR value and returns it
+ * Expects owner secret to be WELL_KNOWN_SECRET
+ *
+ * @param pcr_num Number of PCR to read
+ * @param pcr_value Chunk to save pcr read output
+ * @return NULL in case of TSS error, PCR value otherwise
+ */
+ bool (*read_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value);
+
+ /**
+ * Extends given PCR with given value
+ * Expects owner secret to be WELL_KNOWN_SECRET
+ *
+ * @param pcr_num Number of PCR to extend
+ * @param input Value to extend
+ * @param output Chunk to save PCR value after extension
+ * @return FALSE in case of TSS error, TRUE otherwise
+ */
+ bool (*extend_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t input,
+ chunk_t *output);
+
+ /**
+ * Quote over PCR's
+ * Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK
+ *
+ * @param use_quote2 Version of the Quote function to be used
+ * @param pcr_comp Chunk to save PCR composite structure
+ * @param quote_sig Chunk to save quote operation output
+ * without external data (anti-replay protection)
+ * @return FALSE in case of TSS error, TRUE otherwise
+ */
+ bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
+ chunk_t *quote_sig);
+
+ /**
+ * Mark an extended PCR as selected
+ *
+ * @param pcr Number of the extended PCR
+ * @return TRUE if PCR number is valid
+ */
+ bool (*select_pcr)(pts_t *this, u_int32_t pcr);
+
+ /**
+ * Add an extended PCR with its corresponding value
+ *
+ * @param pcr Number of the extended PCR
+ * @param pcr_before PCR value before extension
+ * @param pcr_after PCR value after extension
+ * @return TRUE if PCR number and register length is valid
+ */
+ bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before,
+ chunk_t pcr_after);
+
+ /**
+ * Constructs and returns TPM Quote Info structure expected from IMC
+ *
+ * @param use_quote2 Version of the TPM_QUOTE_INFO to be constructed
+ * @param use_ver_info Version info is concatenated to TPM_QUOTE_INFO2
+ * @param comp_hash_algo Composite Hash Algorithm
+ * @param pcr_comp Output variable to store PCR Composite
+ * @param quote_info Output variable to store TPM Quote Info
+ * @return FALSE in case of any error, TRUE otherwise
+ */
+ bool (*get_quote_info)(pts_t *this, bool use_quote2, bool ver_info_included,
+ pts_meas_algorithms_t comp_hash_algo,
+ chunk_t *pcr_comp, chunk_t *quote_info);
+
+ /**
+ * Constructs and returns PCR Quote Digest structure expected from IMC
+ *
+ * @param data Calculated TPM Quote Digest
+ * @param signature TPM Quote Signature received from IMC
+ * @return FALSE if signature is not verified
+ */
+ bool (*verify_quote_signature)(pts_t *this, chunk_t data, chunk_t signature);
+
+ /**
+ * Destroys a pts_t object.
+ */
+ void (*destroy)(pts_t *this);
+
+};
+
+/**
+ * Creates an pts_t object
+ *
+ * @param is_imc TRUE if running on an IMC
+ */
+pts_t* pts_create(bool is_imc);
+
+#endif /** PTS_H_ @}*/
diff --git a/src/libpts/pts/pts_creds.c b/src/libpts/pts/pts_creds.c
new file mode 100644
index 000000000..5a6197bdb
--- /dev/null
+++ b/src/libpts/pts/pts_creds.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_creds.h"
+
+#include <debug.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/sets/mem_cred.h>
+
+#include <sys/stat.h>
+
+typedef struct private_pts_creds_t private_pts_creds_t;
+
+/**
+ * Private data of a pts_creds_t object.
+ *
+ */
+struct private_pts_creds_t {
+
+ /**
+ * Public pts_creds_t interface.
+ */
+ pts_creds_t public;
+
+ /**
+ * Credential set
+ */
+ mem_cred_t *creds;
+
+};
+
+METHOD(pts_creds_t, get_set, credential_set_t*,
+ private_pts_creds_t *this)
+{
+ return &this->creds->set;
+}
+
+
+METHOD(pts_creds_t, destroy, void,
+ private_pts_creds_t *this)
+{
+ this->creds->destroy(this->creds);
+ free(this);
+}
+
+/**
+ * Load trusted PTS CA certificates from a directory
+ */
+static void load_cacerts(private_pts_creds_t *this, char *path)
+{
+ enumerator_t *enumerator;
+ struct stat st;
+ char *file;
+
+ DBG1(DBG_PTS, "loading PTS ca certificates from '%s'", path);
+
+ enumerator = enumerator_create_directory(path);
+ if (!enumerator)
+ {
+ return;
+ }
+
+ while (enumerator->enumerate(enumerator, NULL, &file, &st))
+ {
+ certificate_t *cert;
+
+ if (!S_ISREG(st.st_mode))
+ {
+ /* skip special file */
+ continue;
+ }
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file, BUILD_END);
+ if (cert)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ DBG1(DBG_PTS, " ca certificate \"%Y\" lacks ca basic constraint"
+ ", discarded", cert->get_subject(cert));
+ cert->destroy(cert);
+ }
+ else
+ {
+ DBG1(DBG_PTS, " loaded ca certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), file);
+ this->creds->add_cert(this->creds, TRUE, cert);
+ }
+ }
+ else
+ {
+ DBG1(DBG_PTS, " loading ca certificate from '%s' failed", file);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * See header
+ */
+pts_creds_t *pts_creds_create(char *path)
+{
+ private_pts_creds_t *this;
+
+ if (!path)
+ {
+ DBG1(DBG_PTS, "no PTS cacerts directory defined");
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_set = _get_set,
+ .destroy = _destroy,
+ },
+ .creds = mem_cred_create(),
+ );
+
+ load_cacerts(this, path);
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/pts_creds.h b/src/libpts/pts/pts_creds.h
new file mode 100644
index 000000000..eb9c39537
--- /dev/null
+++ b/src/libpts/pts/pts_creds.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_creds pts_creds
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_CREDS_H_
+#define PTS_CREDS_H_
+
+typedef struct pts_creds_t pts_creds_t;
+
+#include <library.h>
+#include <credentials/credential_set.h>
+
+/**
+ * Class implementing a PTS credentials set
+ */
+struct pts_creds_t {
+
+ /**
+ * Get the credential set
+ *
+ * @return credential set
+ */
+ credential_set_t* (*get_set)(pts_creds_t *this);
+
+ /**
+ * Destroys a pts_creds_t object.
+ */
+ void (*destroy)(pts_creds_t *this);
+
+};
+
+/**
+ * Creates an pts_creds_t object
+ *
+ * @param path path to the PTS cacerts directory
+ */
+pts_creds_t* pts_creds_create(char *path);
+
+#endif /** PTS_CREDS_H_ @}*/
diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c
new file mode 100644
index 000000000..282755c0a
--- /dev/null
+++ b/src/libpts/pts/pts_database.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_database.h"
+
+#include <debug.h>
+#include <crypto/hashers/hasher.h>
+
+
+typedef struct private_pts_database_t private_pts_database_t;
+
+/**
+ * Private data of a pts_database_t object.
+ *
+ */
+struct private_pts_database_t {
+
+ /**
+ * Public pts_database_t interface.
+ */
+ pts_database_t public;
+
+ /**
+ * database instance
+ */
+ database_t *db;
+
+};
+
+METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
+ private_pts_database_t *this, char *product)
+{
+ enumerator_t *e;
+
+ /* look for all entries belonging to a product in the files table */
+ e = this->db->query(this->db,
+ "SELECT f.id, f.type, f.path FROM files AS f "
+ "JOIN product_file AS pf ON f.id = pf.file "
+ "JOIN products AS p ON p.id = pf.product "
+ "WHERE p.name = ? AND pf.measurement = 1",
+ DB_TEXT, product, DB_INT, DB_INT, DB_TEXT);
+ return e;
+}
+
+METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*,
+ private_pts_database_t *this, char *product)
+{
+ enumerator_t *e;
+
+ /* look for all entries belonging to a product in the files table */
+ e = this->db->query(this->db,
+ "SELECT f.type, f.path FROM files AS f "
+ "JOIN product_file AS pf ON f.id = pf.file "
+ "JOIN products AS p ON p.id = pf.product "
+ "WHERE p.name = ? AND pf.metadata = 1",
+ DB_TEXT, product, DB_INT, DB_TEXT);
+ return e;
+}
+
+METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
+ private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+ int id, bool is_dir)
+{
+ enumerator_t *e;
+
+ if (is_dir)
+ {
+ e = this->db->query(this->db,
+ "SELECT f.path, fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON fh.file = f.id "
+ "JOIN products AS p ON fh.product = p.id "
+ "WHERE p.name = ? AND fh.directory = ? AND fh.algo = ? "
+ "ORDER BY f.path",
+ DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
+ }
+ else
+ {
+ e = this->db->query(this->db,
+ "SELECT f.path, fh.hash FROM file_hashes AS fh "
+ "JOIN files AS f ON fh.file = f.id "
+ "JOIN products AS p ON fh.product = p.id "
+ "WHERE p.name = ? AND fh.file = ? AND fh.algo = ?",
+ DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
+ }
+ return e;
+}
+
+METHOD(pts_database_t, check_aik_keyid, status_t,
+ private_pts_database_t *this, chunk_t keyid, int *kid)
+{
+ enumerator_t *e;
+
+ /* If the AIK is registered get the primary key */
+ e = this->db->query(this->db,
+ "SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+ if (!e->enumerate(e, kid))
+ {
+ DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid);
+ e->destroy(e);
+ return FAILED;
+ }
+ e->destroy(e);
+
+ return SUCCESS;
+}
+
+METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
+ private_pts_database_t *this, int kid)
+{
+ enumerator_t *e;
+
+ /* look for all entries belonging to an AIK in the components table */
+ e = this->db->query(this->db,
+ "SELECT c.vendor_id, c.name, c.qualifier, kc.depth "
+ "FROM components AS c "
+ "JOIN key_component AS kc ON c.id = kc.component "
+ "WHERE kc.key = ? ORDER BY kc.seq_no",
+ DB_INT, kid, DB_INT, DB_INT, DB_INT, DB_INT);
+ return e;
+}
+
+METHOD(pts_database_t, check_comp_measurement, status_t,
+ private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+ int seq_no, int pcr, pts_meas_algorithms_t algo)
+{
+ enumerator_t *e;
+ chunk_t hash;
+ status_t status = NOT_FOUND;
+
+ e = this->db->query(this->db,
+ "SELECT hash FROM component_hashes "
+ "WHERE component = ? AND key = ? "
+ "AND seq_no = ? AND pcr = ? AND algo = ? ",
+ DB_INT, cid, DB_INT, kid, DB_INT, seq_no,
+ DB_INT, pcr, DB_INT, algo, DB_BLOB);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+
+ while (e->enumerate(e, &hash))
+ {
+ if (chunk_equals(hash, measurement))
+ {
+ status = SUCCESS;
+ break;
+ }
+ else
+ {
+ DBG1(DBG_PTS, "PCR %2d no matching component measurement #%d "
+ "found in database", pcr, seq_no);
+ DBG1(DBG_PTS, " expected: %#B", &hash);
+ DBG1(DBG_PTS, " received: %#B", &measurement);
+ status = FAILED;
+ break;
+ }
+ }
+ e->destroy(e);
+
+ if (status == NOT_FOUND)
+ {
+ DBG1(DBG_PTS, "PCR %2d no measurement #%d "
+ "found in database", pcr, seq_no);
+ }
+
+ return status;
+}
+
+METHOD(pts_database_t, insert_comp_measurement, status_t,
+ private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+ int seq_no, int pcr, pts_meas_algorithms_t algo)
+{
+ int id;
+
+ if (this->db->execute(this->db, &id,
+ "INSERT INTO component_hashes "
+ "(component, key, seq_no, pcr, algo, hash) "
+ "VALUES (?, ?, ?, ?, ?, ?)",
+ DB_INT, cid, DB_INT, kid, DB_INT, seq_no, DB_INT, pcr,
+ DB_INT, algo, DB_BLOB, measurement) == 1)
+ {
+ return SUCCESS;
+ }
+
+ DBG1(DBG_PTS, "could not insert component measurement into database");
+ return FAILED;
+}
+
+METHOD(pts_database_t, delete_comp_measurements, int,
+ private_pts_database_t *this, int cid, int kid)
+{
+ return this->db->execute(this->db, NULL,
+ "DELETE FROM component_hashes "
+ "WHERE component = ? AND key = ?",
+ DB_INT, cid, DB_INT, kid);
+}
+
+METHOD(pts_database_t, get_comp_measurement_count, status_t,
+ private_pts_database_t *this, pts_comp_func_name_t *comp_name,
+ chunk_t keyid, pts_meas_algorithms_t algo, int *cid, int *kid, int *count)
+{
+ enumerator_t *e;
+ status_t status = SUCCESS;
+
+ /* Initialize count */
+ *count = 0;
+
+ if (_check_aik_keyid(this, keyid, kid) != SUCCESS)
+ {
+ return FAILED;
+ }
+
+ /* Get the primary key of the Component Functional Name */
+ e = this->db->query(this->db,
+ "SELECT id FROM components "
+ " WHERE vendor_id = ? AND name = ? AND qualifier = ?",
+ DB_INT, comp_name->get_vendor_id(comp_name),
+ DB_INT, comp_name->get_name(comp_name),
+ DB_INT, comp_name->get_qualifier(comp_name),
+ DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+ if (!e->enumerate(e, cid))
+ {
+ DBG1(DBG_PTS, "component functional name not found in database");
+ e->destroy(e);
+ return FAILED;
+ }
+ e->destroy(e);
+
+ /* Get the number of stored measurements for a given AIK and component */
+ e = this->db->query(this->db,
+ "SELECT COUNT(*) FROM component_hashes AS ch "
+ "WHERE component = ? AND key = ? AND algo = ?",
+ DB_INT, *cid, DB_INT, *kid, DB_INT, algo, DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_PTS, "no database query enumerator returned");
+ return FAILED;
+ }
+ if (!e->enumerate(e, count))
+ {
+ DBG1(DBG_PTS, "no component measurement count returned from database");
+ status = FAILED;
+ }
+ e->destroy(e);
+
+ return status;
+}
+
+METHOD(pts_database_t, destroy, void,
+ private_pts_database_t *this)
+{
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_database_t *pts_database_create(char *uri)
+{
+ private_pts_database_t *this;
+
+ INIT(this,
+ .public = {
+ .create_file_meas_enumerator = _create_file_meas_enumerator,
+ .create_file_meta_enumerator = _create_file_meta_enumerator,
+ .create_comp_evid_enumerator = _create_comp_evid_enumerator,
+ .create_file_hash_enumerator = _create_file_hash_enumerator,
+ .check_aik_keyid = _check_aik_keyid,
+ .check_comp_measurement = _check_comp_measurement,
+ .insert_comp_measurement = _insert_comp_measurement,
+ .delete_comp_measurements = _delete_comp_measurements,
+ .get_comp_measurement_count = _get_comp_measurement_count,
+ .destroy = _destroy,
+ },
+ .db = lib->db->create(lib->db, uri),
+ );
+
+ if (!this->db)
+ {
+ DBG1(DBG_PTS,
+ "failed to connect to PTS file measurement database '%s'", uri);
+ free(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h
new file mode 100644
index 000000000..a9a68ac76
--- /dev/null
+++ b/src/libpts/pts/pts_database.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_database pts_database
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_DATABASE_H_
+#define PTS_DATABASE_H_
+
+typedef struct pts_database_t pts_database_t;
+
+#include "pts_meas_algo.h"
+#include "components/pts_comp_func_name.h"
+#include <library.h>
+
+/**
+ * Class implementing the PTS File Measurement database
+ *
+ */
+struct pts_database_t {
+
+ /**
+ * Get files/directories to be measured by PTS
+ *
+ * @param product Software product (os, vpn client, etc.)
+ * @return Enumerator over all matching files/directories
+ */
+ enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this,
+ char *product);
+
+ /**
+ * Get files/directories to request metadata of
+ *
+ * @param product Software product (os, vpn client, etc.)
+ * @return Enumerator over all matching files/directories
+ */
+ enumerator_t* (*create_file_meta_enumerator)(pts_database_t *this,
+ char *product);
+
+ /**
+ * Get stored measurement hash for single file or directory entries
+ *
+ * @param product Software product (os, vpn client, etc.)
+ * @param algo Hash algorithm used for measurement
+ * @param id Primary key of measured file/directory
+ * @param is_dir TRUE if directory was measured
+ * @return Enumerator over all matching measurement hashes
+ */
+ enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
+ char *product, pts_meas_algorithms_t algo,
+ int id, bool is_dir);
+
+ /**
+ * Check if an AIK given by its keyid is registered in the database
+ *
+ * @param keyid AIK keyid (SHA-1 hash of the AIK public key info)
+ * @param kid Primary key of AIK entry in keys table
+ * @return SUCCESS if AIK is present, FAILED otherwise
+ */
+ status_t (*check_aik_keyid)(pts_database_t *this, chunk_t keyid, int *kid);
+
+ /**
+ * Get functional components to request evidence of
+ *
+ * @param kid Primary key of AIK entry in keys table
+ * @return Enumerator over all matching components
+ */
+ enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid);
+
+ /**
+ * Check a functional component measurement against value stored in database
+ *
+ * @param measurement measurement hash
+ * @param cid Primary key of Component Functional Name entry
+ * @param kid Primary key of AIK entry in keys table
+ * @param seq_no Measurement sequence number
+ * @param prc Number of the PCR the measurement was extended into
+ * @param algo Hash algorithm used for measurement
+ * @return SUCCESS if check was successful
+ */
+ status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
+ int cid, int kid, int seq_no, int pcr,
+ pts_meas_algorithms_t algo);
+
+ /**
+ * Insert a functional component measurement into the database
+ *
+ * @param measurement Measurement hash
+ * @param cid Primary key of Component Functional Name entry
+ * @param kid Primary key of AIK entry in keys table
+ * @param seq_no Measurement sequence number
+ * @param prc Number of the PCR the measurement was extended into
+ * @param algo Hash algorithm used for measurement
+ * @return SUCCESS if INSERT was successful
+ */
+ status_t (*insert_comp_measurement)(pts_database_t *this, chunk_t measurement,
+ int cid, int kid, int seq_no, int pcr,
+ pts_meas_algorithms_t algo);
+
+ /**
+ * Delete functional component measurements from the database
+ *
+ * @param cid Primary key of Component Functional Name entry
+ * @param kid Primary key of AIK entry in keys table
+ * @return number of deleted measurement entries
+ */
+ int (*delete_comp_measurements)(pts_database_t *this, int cid, int kid);
+
+ /**
+ * Get the number of measurements for a functional component and AIK
+ *
+ * @param comp_name Component Functional Name
+ * @param keyid SHA-1 hash of AIK public key info
+ * @param algo Hash algorithm used for measurement
+ * @param cid Primary key of Component Functional Name entry
+ * @param kid Primary key of AIK entry in keys table
+ * @param count measurement count
+ * @return SUCCESS if COUNT was successful
+ */
+ status_t (*get_comp_measurement_count)(pts_database_t *this,
+ pts_comp_func_name_t *comp_name, chunk_t keyid,
+ pts_meas_algorithms_t algo, int *cid, int *kid,
+ int *count);
+
+ /**
+ * Destroys a pts_database_t object.
+ */
+ void (*destroy)(pts_database_t *this);
+
+};
+
+/**
+ * Creates an pts_database_t object
+ *
+ * @param uri database uri
+ */
+pts_database_t* pts_database_create(char *uri);
+
+#endif /** PTS_DATABASE_H_ @}*/
diff --git a/src/libpts/pts/pts_dh_group.c b/src/libpts/pts/pts_dh_group.c
new file mode 100644
index 000000000..fb141327f
--- /dev/null
+++ b/src/libpts/pts/pts_dh_group.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_dh_group.h"
+
+#include <debug.h>
+
+/**
+ * Described in header.
+ */
+bool pts_dh_group_probe(pts_dh_group_t *dh_groups)
+{
+ enumerator_t *enumerator;
+ diffie_hellman_group_t dh_group;
+ const char *plugin_name;
+ char format1[] = " %s PTS DH group %N[%s] available";
+ char format2[] = " %s PTS DH group %N not available";
+
+ *dh_groups = PTS_DH_GROUP_NONE;
+
+ enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
+ {
+ if (dh_group == MODP_1024_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE2;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == MODP_1536_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE5;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == MODP_2048_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE14;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == ECP_256_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE19;
+ DBG2(DBG_PTS, format1, "mandatory", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ else if (dh_group == ECP_384_BIT)
+ {
+ *dh_groups |= PTS_DH_GROUP_IKE20;
+ DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
+ dh_group, plugin_name);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (*dh_groups & PTS_DH_GROUP_IKE19)
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBG1(DBG_PTS, format2, "mandatory", diffie_hellman_group_names,
+ ECP_256_BIT);
+ }
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups)
+{
+ if (strcaseeq(dh_group, "ecp384"))
+ {
+ /* nothing to update, all groups are supported */
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "ecp256"))
+ {
+ /* remove DH group 20 */
+ *dh_groups &= ~PTS_DH_GROUP_IKE20;
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp2048"))
+ {
+ /* remove DH groups 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19);
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp1536"))
+ {
+ /* remove DH groups 14, 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
+ PTS_DH_GROUP_IKE14);
+ return TRUE;
+ }
+ if (strcaseeq(dh_group, "modp1024"))
+ {
+ /* remove DH groups 5, 14, 19 and 20 */
+ *dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
+ PTS_DH_GROUP_IKE14 | PTS_DH_GROUP_IKE5);
+ return TRUE;
+ }
+ DBG1(DBG_PTS, "unknown DH group '%s' configured", dh_group);
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups,
+ pts_dh_group_t offered_dh_groups)
+{
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE20) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE20))
+ {
+ return PTS_DH_GROUP_IKE20;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE19) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE19))
+ {
+ return PTS_DH_GROUP_IKE19;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE14) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE14))
+ {
+ return PTS_DH_GROUP_IKE14;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE5) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE5))
+ {
+ return PTS_DH_GROUP_IKE5;
+ }
+ if ((supported_dh_groups & PTS_DH_GROUP_IKE2) &&
+ (offered_dh_groups & PTS_DH_GROUP_IKE2))
+ {
+ return PTS_DH_GROUP_IKE2;
+ }
+ return PTS_DH_GROUP_NONE;
+}
+
+/**
+ * Described in header.
+ */
+diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
+{
+ switch (dh_group)
+ {
+ case PTS_DH_GROUP_IKE2:
+ return MODP_1024_BIT;
+ case PTS_DH_GROUP_IKE5:
+ return MODP_1536_BIT;
+ case PTS_DH_GROUP_IKE14:
+ return MODP_2048_BIT;
+ case PTS_DH_GROUP_IKE19:
+ return ECP_256_BIT;
+ case PTS_DH_GROUP_IKE20:
+ return ECP_384_BIT;
+ default:
+ return MODP_NONE;
+ }
+}
diff --git a/src/libpts/pts/pts_dh_group.h b/src/libpts/pts/pts_dh_group.h
new file mode 100644
index 000000000..8664a4b84
--- /dev/null
+++ b/src/libpts/pts/pts_dh_group.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_dh_group pts_dh_group
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_DH_GROUP_H_
+#define PTS_DH_GROUP_H_
+
+#include <library.h>
+#include <crypto/diffie_hellman.h>
+
+typedef enum pts_dh_group_t pts_dh_group_t;
+
+/**
+ * PTS Diffie Hellman Group Values
+ */
+enum pts_dh_group_t {
+ /** No DH Group */
+ PTS_DH_GROUP_NONE = 0,
+ /** IKE Group 2 */
+ PTS_DH_GROUP_IKE2 = (1<<15),
+ /** IKE Group 5 */
+ PTS_DH_GROUP_IKE5 = (1<<14),
+ /** IKE Group 14 */
+ PTS_DH_GROUP_IKE14 = (1<<13),
+ /** IKE Group 19 */
+ PTS_DH_GROUP_IKE19 = (1<<12),
+ /** IKE Group 20 */
+ PTS_DH_GROUP_IKE20 = (1<<11),
+};
+
+/**
+ * Diffie-Hellman Group Values
+ * see section 3.8.6 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|2|3|4|5|R|R|R|R|R|R|R|R|R|R|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+/**
+ * Probe available PTS Diffie-Hellman groups
+ *
+ * @param dh_groups returns set of available DH groups
+ * @return TRUE if mandatory DH groups are available
+ */
+bool pts_dh_group_probe(pts_dh_group_t *dh_groups);
+
+/**
+ * Update supported Diffie-Hellman groups according to configuration
+ *
+ * modp1024: PTS_DH_GROUP_IKE2
+ * modp1536: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5
+ * modp2048: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14
+ * ecp256: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14 |
+ * PTS_DH_GROUP_IKE19
+ * ecp384: PTS_DH_GROUP_IKE2 | PTS_DH_GROUP_IKE5 | PTS_DH_GROUP_IKE14 |
+ * PTS_DH_GROUP_IKE19 | PTS_DH_GROUP_IKE20
+ *
+ * The PTS-IMC is expected to select the strongest supported group
+ *
+ * @param dh_group configured DH group
+ * @param dh_groups returns set of available DH groups
+ */
+bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups);
+
+/**
+ * Select the strongest supported Diffie-Hellman group
+ * among a set of offered DH groups
+ *
+ * @param supported_groups set of supported DH groups
+ * @param offered_groups set of offered DH groups
+ * @return selected DH group
+ */
+pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups,
+ pts_dh_group_t offered_dh_groups);
+
+/**
+ * Convert pts_dh_group_t to diffie_hellman_group_t
+ *
+ * @param dh_group PTS DH group type
+ * @return IKE DH group type
+ */
+diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group);
+
+#endif /** PTS_DH_GROUP_H_ @}*/
diff --git a/src/libpts/pts/pts_error.c b/src/libpts/pts/pts_error.c
new file mode 100644
index 000000000..6e914b2a9
--- /dev/null
+++ b/src/libpts/pts/pts_error.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_error.h"
+
+#include <bio/bio_writer.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+ENUM(pts_error_code_names, TCG_PTS_RESERVED_ERROR, TCG_PTS_UNABLE_DET_PCR,
+ "Reserved Error",
+ "Hash Algorithm Not Supported",
+ "Invalid Path",
+ "File Not Found",
+ "Registry Not Supported",
+ "Registry Key Not Found",
+ "D-H Group Not Supported",
+ "DH-PN Nonce Not Acceptable",
+ "Invalid Functional Name Family",
+ "TPM Version Information Unavailable",
+ "Invalid File Pathname Delimiter",
+ "PTS Operation Not Supported",
+ "Unable To Update Reference Manifest",
+ "Unable To Perform Local Validation",
+ "Unable To Collect Current Evidence",
+ "Unable To Determine Transitive Trust Chain",
+ "Unable To Determine PCR"
+);
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_uint16(writer, algorithms);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED,
+ msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, 0x0000);
+ writer->write_uint16(writer, dh_groups);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED,
+ msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+
+ writer = bio_writer_create(4);
+ writer->write_uint16(writer, min_nonce_len);
+ writer->write_uint16(writer, max_nonce_len);
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH,
+ msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
diff --git a/src/libpts/pts/pts_error.h b/src/libpts/pts/pts_error.h
new file mode 100644
index 000000000..9a53abd98
--- /dev/null
+++ b/src/libpts/pts/pts_error.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_error pts_error
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_ERROR_H_
+#define PTS_ERROR_H_
+
+typedef enum pts_error_code_t pts_error_code_t;
+
+#include "pts_meas_algo.h"
+#include "pts_dh_group.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+
+#define PTS_MIN_NONCE_LEN 17
+#define PTS_MAX_NONCE_LEN 0xffff
+
+/**
+ * PTS Attestation Error Codes
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_error_code_t {
+ TCG_PTS_RESERVED_ERROR = 0,
+ TCG_PTS_HASH_ALG_NOT_SUPPORTED = 1,
+ TCG_PTS_INVALID_PATH = 2,
+ TCG_PTS_FILE_NOT_FOUND = 3,
+ TCG_PTS_REG_NOT_SUPPORTED = 4,
+ TCG_PTS_REG_KEY_NOT_FOUND = 5,
+ TCG_PTS_DH_GRPS_NOT_SUPPORTED = 6,
+ TCG_PTS_BAD_NONCE_LENGTH = 7,
+ TCG_PTS_INVALID_NAME_FAM = 8,
+ TCG_PTS_TPM_VERS_NOT_SUPPORTED = 9,
+ TCG_PTS_INVALID_DELIMITER = 10,
+ TCG_PTS_OPERATION_NOT_SUPPORTED = 11,
+ TCG_PTS_RM_ERROR = 12,
+ TCG_PTS_UNABLE_LOCAL_VAL = 13,
+ TCG_PTS_UNABLE_CUR_EVID = 14,
+ TCG_PTS_UNABLE_DET_TTC = 15,
+ TCG_PTS_UNABLE_DET_PCR = 16,
+};
+
+/**
+ * enum name for pts_error_code_t.
+ */
+extern enum_name_t *pts_error_code_names;
+
+/**
+ * Creates a PTS Hash Algorithm Not Supported Error Attribute
+ * see section 4.2.2 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param algorithms supported measurement hash algorithms
+ */
+pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms);
+
+/**
+ * Creates a PTS DH Group Not Supported Error Attribute
+ * see section 4.2.4 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param dh_groups supported DH groups
+ */
+pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups);
+
+/**
+ * Creates a PTS DH PN Nonce Not Supported Error Attribute
+ * see section 4.2.5 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * @param min_nonce_len minimum nonce length
+ * @param max_nonce_len maximum nonce length
+ */
+pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len);
+
+#endif /** PTS_ERROR_H_ @}*/
diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c
new file mode 100644
index 000000000..f0e0d4c0a
--- /dev/null
+++ b/src/libpts/pts/pts_file_meas.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_meas.h"
+
+#include <utils/linked_list.h>
+#include <debug.h>
+
+typedef struct private_pts_file_meas_t private_pts_file_meas_t;
+
+/**
+ * Private data of a pts_file_meas_t object.
+ *
+ */
+struct private_pts_file_meas_t {
+
+ /**
+ * Public pts_file_meas_t interface.
+ */
+ pts_file_meas_t public;
+
+ /**
+ * ID of PTS File Measurement Request
+ */
+ u_int16_t request_id;
+
+ /**
+ * List of File Measurements
+ */
+ linked_list_t *list;
+};
+
+typedef struct entry_t entry_t;
+
+/**
+ * PTS File Measurement entry
+ */
+struct entry_t {
+ char *filename;
+ chunk_t measurement;
+};
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *entry)
+{
+ if (entry)
+ {
+ free(entry->filename);
+ free(entry->measurement.ptr);
+ free(entry);
+ }
+}
+
+METHOD(pts_file_meas_t, get_request_id, u_int16_t,
+ private_pts_file_meas_t *this)
+{
+ return this->request_id;
+}
+
+METHOD(pts_file_meas_t, get_file_count, int,
+ private_pts_file_meas_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(pts_file_meas_t, add, void,
+ private_pts_file_meas_t *this, char *filename, chunk_t measurement)
+{
+ entry_t *entry;
+
+ entry = malloc_thing(entry_t);
+ entry->filename = strdup(filename);
+ entry->measurement = chunk_clone(measurement);
+
+ this->list->insert_last(this->list, entry);
+}
+
+/**
+ * Enumerate file measurement entries
+ */
+static bool entry_filter(void *null, entry_t **entry, char **filename,
+ void *i2, chunk_t *measurement)
+{
+ *filename = (*entry)->filename;
+ *measurement = (*entry)->measurement;
+ return TRUE;
+}
+
+METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
+ private_pts_file_meas_t *this)
+{
+ return enumerator_create_filter(this->list->create_enumerator(this->list),
+ (void*)entry_filter, NULL, NULL);
+}
+
+METHOD(pts_file_meas_t, verify, bool,
+ private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
+{
+ char *filename;
+ chunk_t measurement;
+ entry_t *entry;
+ enumerator_t *enumerator;
+ bool found, success = TRUE;
+
+ while (e_hash->enumerate(e_hash, &filename, &measurement))
+ {
+ found = FALSE;
+
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!is_dir || streq(filename, entry->filename))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ DBG1(DBG_PTS, " no measurement found for '%s'", filename);
+ success = FALSE;
+ continue;
+ }
+ if (chunk_equals(measurement, entry->measurement))
+ {
+ DBG2(DBG_PTS, " %#B for '%s' is ok", &measurement, filename);
+ }
+ else
+ {
+ DBG1(DBG_PTS, " %#B for '%s' is incorrect", &measurement, filename);
+ success = FALSE;
+ }
+ if (!is_dir)
+ {
+ break;
+ }
+ }
+ return success;
+}
+
+METHOD(pts_file_meas_t, destroy, void,
+ private_pts_file_meas_t *this)
+{
+ this->list->destroy_function(this->list, (void *)free_entry);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
+{
+ private_pts_file_meas_t *this;
+
+ INIT(this,
+ .public = {
+ .get_request_id = _get_request_id,
+ .get_file_count = _get_file_count,
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ .verify = _verify,
+ .destroy = _destroy,
+ },
+ .request_id = request_id,
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h
new file mode 100644
index 000000000..3ebb5c2a0
--- /dev/null
+++ b/src/libpts/pts/pts_file_meas.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_meas pts_file_meas
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_MEAS_H_
+#define PTS_FILE_MEAS_H_
+
+#include <library.h>
+
+typedef struct pts_file_meas_t pts_file_meas_t;
+
+/**
+ * Class storing PTS File Measurements
+ */
+struct pts_file_meas_t {
+
+ /**
+ * Get the ID of the PTS File Measurement Request
+ *
+ * @return ID of PTS File Measurement Request
+ */
+ u_int16_t (*get_request_id)(pts_file_meas_t *this);
+
+ /**
+ * Get the number of measured files
+ *
+ * @return Number of measured files
+ */
+ int (*get_file_count)(pts_file_meas_t *this);
+
+ /**
+ * Add a PTS File Measurement
+ *
+ * @param filename Name of measured file or directory
+ * @param measurement PTS Measurement hash
+ */
+ void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
+
+ /**
+ * Create a PTS File Measurement enumerator
+ *
+ * @return Enumerator returning filename and measurement
+ */
+ enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
+
+ /**
+ * Verify stored hashes against PTS File Measurements
+ *
+ * @param e_hash Hash enumerator
+ * @paraem is_dir TRUE for directory contents hashes
+ * @return TRUE if all hashes match a measurement
+ */
+ bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir);
+
+ /**
+ * Destroys a pts_file_meas_t object.
+ */
+ void (*destroy)(pts_file_meas_t *this);
+
+};
+
+/**
+ * Creates a pts_file_meas_t object
+ *
+ * @param request_id ID of PTS File Measurement Request
+ */
+pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
+
+#endif /** PTS_FILE_MEAS_H_ @}*/
diff --git a/src/libpts/pts/pts_file_meta.c b/src/libpts/pts/pts_file_meta.c
new file mode 100644
index 000000000..6ed1c01b4
--- /dev/null
+++ b/src/libpts/pts/pts_file_meta.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_meta.h"
+
+#include <utils/linked_list.h>
+#include <debug.h>
+
+typedef struct private_pts_file_meta_t private_pts_file_meta_t;
+
+/**
+ * Private data of a pts_file_meta_t object.
+ *
+ */
+struct private_pts_file_meta_t {
+
+ /**
+ * Public pts_file_meta_t interface.
+ */
+ pts_file_meta_t public;
+
+ /**
+ * List of File Metadata
+ */
+ linked_list_t *list;
+};
+
+/**
+ * Free an pts_file_metadata_t object
+ */
+static void free_entry(pts_file_metadata_t *entry)
+{
+ if (entry)
+ {
+ free(entry->filename);
+ free(entry);
+ }
+}
+
+METHOD(pts_file_meta_t, get_file_count, int,
+ private_pts_file_meta_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(pts_file_meta_t, add, void,
+ private_pts_file_meta_t *this, pts_file_metadata_t *metadata)
+{
+ this->list->insert_last(this->list, metadata);
+}
+
+METHOD(pts_file_meta_t, create_enumerator, enumerator_t*,
+ private_pts_file_meta_t *this)
+{
+ return this->list->create_enumerator(this->list);
+}
+
+METHOD(pts_file_meta_t, destroy, void,
+ private_pts_file_meta_t *this)
+{
+ this->list->destroy_function(this->list, (void *)free_entry);
+ free(this);
+}
+
+/**
+ * See header
+ */
+pts_file_meta_t *pts_file_meta_create()
+{
+ private_pts_file_meta_t *this;
+
+ INIT(this,
+ .public = {
+ .get_file_count = _get_file_count,
+ .add = _add,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libpts/pts/pts_file_meta.h b/src/libpts/pts/pts_file_meta.h
new file mode 100644
index 000000000..3f1813306
--- /dev/null
+++ b/src/libpts/pts/pts_file_meta.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_meta pts_file_meta
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_META_H_
+#define PTS_FILE_META_H_
+
+#include "pts_file_type.h"
+
+#include <time.h>
+#include <library.h>
+
+typedef struct pts_file_meta_t pts_file_meta_t;
+typedef struct pts_file_metadata_t pts_file_metadata_t;
+
+/**
+ * Structure holding file metadata
+ */
+struct pts_file_metadata_t {
+ pts_file_type_t type;
+ u_int64_t filesize;
+ u_int64_t created;
+ u_int64_t modified;
+ u_int64_t accessed;
+ u_int64_t owner;
+ u_int64_t group;
+ char *filename;
+};
+
+/**
+ * Class storing PTS File Metadata
+ */
+struct pts_file_meta_t {
+
+ /**
+ * Get the number of files
+ *
+ * @return Number of files
+ */
+ int (*get_file_count)(pts_file_meta_t *this);
+
+ /**
+ * Add PTS File Metadata
+ *
+ * @param filename Name of measured file or directory
+ * @param metadata File metadata
+ */
+ void (*add)(pts_file_meta_t *this, pts_file_metadata_t *metadata);
+
+ /**
+ * Create a PTS File Metadata enumerator
+ *
+ * @return Enumerator returning file metadata
+ */
+ enumerator_t* (*create_enumerator)(pts_file_meta_t *this);
+
+ /**
+ * Destroys a pts_file_meta_t object.
+ */
+ void (*destroy)(pts_file_meta_t *this);
+
+};
+
+/**
+ * Creates a pts_file_meta_t object
+ */
+pts_file_meta_t* pts_file_meta_create();
+
+#endif /** PTS_FILE_MEAS_H_ @}*/
diff --git a/src/libpts/pts/pts_file_type.c b/src/libpts/pts/pts_file_type.c
new file mode 100644
index 000000000..fe849dea4
--- /dev/null
+++ b/src/libpts/pts/pts_file_type.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_file_type.h"
+
+ENUM(pts_file_type_names, PTS_FILE_OTHER, PTS_FILE_SOCKET,
+ "Other",
+ "FIFO",
+ "Character-Special",
+ "Reserved-3",
+ "Directory",
+ "Reserved-5",
+ "Block-Special",
+ "Reserved-7",
+ "Regular",
+ "Reserved-9",
+ "Symbolic-Link",
+ "Reserved-11",
+ "Socket"
+);
+
diff --git a/src/libpts/pts/pts_file_type.h b/src/libpts/pts/pts_file_type.h
new file mode 100644
index 000000000..c1d236888
--- /dev/null
+++ b/src/libpts/pts/pts_file_type.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_file_type pts_file_type
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_FILE_TYPE_H_
+#define PTS_FILE_TYPE_H_
+
+#include <library.h>
+
+typedef enum pts_file_type_t pts_file_type_t;
+
+/**
+ * PTS File Type
+ * see section 3.17.3 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum pts_file_type_t {
+ /** Either unknown or different from standardized types */
+ PTS_FILE_OTHER = 0x0000,
+ /** Pipe communication file */
+ PTS_FILE_FIFO = 0x0001,
+ /** Character special file */
+ PTS_FILE_CHAR_SPEC = 0x0002,
+ /** Reserved */
+ PTS_FILE_RESERVED_3 = 0x0003,
+ /** Directory */
+ PTS_FILE_DIRECTORY = 0x0004,
+ /** Reserved */
+ PTS_FILE_RESERVED_5 = 0x0005,
+ /** Block special file */
+ PTS_FILE_BLOCK_SPEC = 0x0006,
+ /** Reserved */
+ PTS_FILE_RESERVED_7 = 0x0007,
+ /** Regular file */
+ PTS_FILE_REGULAR = 0x0008,
+ /** Reserved */
+ PTS_FILE_RESERVED_9 = 0x0009,
+ /** Symbolic link */
+ PTS_FILE_SYM_LINK = 0x000A,
+ /** Reserved */
+ PTS_FILE_RESERVED_11 = 0x000B,
+ /** Socket communication special file */
+ PTS_FILE_SOCKET = 0x000C,
+};
+
+extern enum_name_t *pts_file_type_names;
+
+#endif /** PTS_FILE_TYPE_H_ @}*/
diff --git a/src/libpts/pts/pts_meas_algo.c b/src/libpts/pts/pts_meas_algo.c
new file mode 100644
index 000000000..865857d3c
--- /dev/null
+++ b/src/libpts/pts/pts_meas_algo.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pts_meas_algo.h"
+
+#include <debug.h>
+
+ENUM(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_SHA384,
+ "None",
+ "SHA1",
+ "SHA256",
+ "SHA384"
+);
+
+/**
+ * Described in header.
+ */
+bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
+{
+ enumerator_t *enumerator;
+ hash_algorithm_t hash_alg;
+ const char *plugin_name;
+ char format1[] = " %s PTS measurement algorithm %N[%s] available";
+ char format2[] = " %s PTS measurement algorithm %N not available";
+
+ *algorithms = 0;
+
+ enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name))
+ {
+ if (hash_alg == HASH_SHA1)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA1;
+ DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ else if (hash_alg == HASH_SHA256)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA256;
+ DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ else if (hash_alg == HASH_SHA384)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA384;
+ DBG2(DBG_PTS, format1, "optional ", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA384))
+ {
+ DBG1(DBG_PTS, format2, "optional ", hash_algorithm_names, HASH_SHA384);
+ }
+ if ((*algorithms & PTS_MEAS_ALGO_SHA1) &&
+ (*algorithms & PTS_MEAS_ALGO_SHA256))
+ {
+ return TRUE;
+ }
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA1))
+ {
+ DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA1);
+ }
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA256))
+ {
+ DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA256);
+ }
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms)
+{
+ if (strcaseeq(hash_alg, "sha384") || strcaseeq(hash_alg, "sha2_384"))
+ {
+ /* nothing to update, all algorithms are supported */
+ return TRUE;
+ }
+ if (strcaseeq(hash_alg, "sha256") || strcaseeq(hash_alg, "sha2_256"))
+ {
+ /* remove SHA384algorithm */
+ *algorithms &= ~PTS_MEAS_ALGO_SHA384;
+ return TRUE;
+ }
+ if (strcaseeq(hash_alg, "sha1"))
+ {
+ /* remove SHA384 and SHA256 algorithms */
+ *algorithms &= ~(PTS_MEAS_ALGO_SHA384 | PTS_MEAS_ALGO_SHA256);
+ return TRUE;
+ }
+ DBG1(DBG_PTS, "unknown hash algorithm '%s' configured", hash_alg);
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
+ pts_meas_algorithms_t offered_algos)
+{
+ if ((supported_algos & PTS_MEAS_ALGO_SHA384) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA384))
+ {
+ return PTS_MEAS_ALGO_SHA384;
+ }
+ if ((supported_algos & PTS_MEAS_ALGO_SHA256) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA256))
+ {
+ return PTS_MEAS_ALGO_SHA256;
+ }
+ if ((supported_algos & PTS_MEAS_ALGO_SHA1) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA1))
+ {
+ return PTS_MEAS_ALGO_SHA1;
+ }
+ return PTS_MEAS_ALGO_NONE;
+}
+
+/**
+ * Described in header.
+ */
+hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm)
+{
+ switch (algorithm)
+ {
+ case PTS_MEAS_ALGO_SHA1:
+ return HASH_SHA1;
+ case PTS_MEAS_ALGO_SHA256:
+ return HASH_SHA256;
+ case PTS_MEAS_ALGO_SHA384:
+ return HASH_SHA384;
+ default:
+ return HASH_UNKNOWN;
+ }
+}
+
+/**
+ * Described in header.
+ */
+size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm)
+{
+ switch (algorithm)
+ {
+ case PTS_MEAS_ALGO_SHA1:
+ return HASH_SIZE_SHA1;
+ case PTS_MEAS_ALGO_SHA256:
+ return HASH_SIZE_SHA256;
+ case PTS_MEAS_ALGO_SHA384:
+ return HASH_SIZE_SHA384;
+ case PTS_MEAS_ALGO_NONE:
+ default:
+ return 0;
+ }
+}
+
diff --git a/src/libpts/pts/pts_meas_algo.h b/src/libpts/pts/pts_meas_algo.h
new file mode 100644
index 000000000..1d96a4946
--- /dev/null
+++ b/src/libpts/pts/pts_meas_algo.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_meas_algo pts_meas_algo
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_MEAS_ALGO_H_
+#define PTS_MEAS_ALGO_H_
+
+#include <library.h>
+#include <crypto/hashers/hasher.h>
+
+typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
+
+/**
+ * PTS Measurement Algorithms
+ */
+enum pts_meas_algorithms_t {
+ PTS_MEAS_ALGO_NONE = 0,
+ PTS_MEAS_ALGO_SHA1 = (1<<15),
+ PTS_MEAS_ALGO_SHA256 = (1<<14),
+ PTS_MEAS_ALGO_SHA384 = (1<<13),
+};
+
+/**
+ * enum name for pts_meas_algorithms_t.
+ */
+extern enum_name_t *pts_meas_algorithm_names;
+
+/**
+ * Diffie-Hellman Hash Algorithm Values
+ * see section 3.8.5 of PTS Protocol: Binding to TNC IF-M Specification
+ *
+ * 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|2|3|R|R|R|R|R|R|R|R|R|R|R|R|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+/**
+ * Probe available PTS measurement algorithms
+ *
+ * @param algorithms set of available algorithms
+ * @return TRUE if mandatory algorithms are available
+ */
+bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms);
+
+/**
+ * Update supported PTS measurement algorithms according to configuration
+ *
+ * sha1 : PTS_MEAS_ALGO_SHA1
+ * sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
+ * sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
+ *
+ * The PTS-IMC is expected to select the strongest supported algorithm
+ *
+ * @param hash_alg configured hash algorithm
+ * @param algorithms returns set of available PTS measurement algorithms
+ */
+bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms);
+
+/**
+ * Select the strongest PTS measurement algorithm
+ * among a set of offered PTS measurement algorithms
+ *
+ * @param supported_algos set of supported PTS measurement algorithms
+ * @param offered_algos set of offered PTS measurements algorithms
+ * @return selected algorithm
+ */
+pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
+ pts_meas_algorithms_t offered_algos);
+
+/**
+ * Convert pts_meas_algorithms_t to hash_algorithm_t
+ *
+ * @param algorithm PTS measurement algorithm type
+ * @return libstrongswan hash algorithm type
+ */
+hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm);
+
+/**
+ * Return the hash size of a pts_meas_algorithm
+ *
+ * @param algorithm PTS measurement algorithm type
+ * @return hash size in bytes
+ */
+size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm);
+
+#endif /** PTS_MEAS_ALGO_H_ @}*/
diff --git a/src/libpts/pts/pts_proto_caps.h b/src/libpts/pts/pts_proto_caps.h
new file mode 100644
index 000000000..4346d9b79
--- /dev/null
+++ b/src/libpts/pts/pts_proto_caps.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_proto_caps pts_proto_caps
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_PROTO_CAPS_H_
+#define PTS_PROTO_CAPS_H_
+
+typedef enum pts_proto_caps_flag_t pts_proto_caps_flag_t;
+
+#include <library.h>
+
+/**
+ * PTS Protocol Capabilities Flags
+ */
+enum pts_proto_caps_flag_t {
+ /** XML based Evidence Support flag */
+ PTS_PROTO_CAPS_X = (1<<0),
+ /** Trusted Platform Evidence flag */
+ PTS_PROTO_CAPS_T = (1<<1),
+ /** DH Nonce Negotiation Support flag */
+ PTS_PROTO_CAPS_D = (1<<2),
+ /** Verification Support flag */
+ PTS_PROTO_CAPS_V = (1<<3),
+ /** Current (In-Memory) Evidence Support flag */
+ PTS_PROTO_CAPS_C = (1<<4),
+};
+
+#endif /** PTS_PROTO_CAPS_H_ @}*/
diff --git a/src/libpts/pts/pts_req_func_comp_evid.h b/src/libpts/pts/pts_req_func_comp_evid.h
new file mode 100644
index 000000000..bbf5bbf5b
--- /dev/null
+++ b/src/libpts/pts/pts_req_func_comp_evid.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_req_func_comp_evid pts_req_func_comp_evid
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_REQ_FUNC_COMP_EVID_H_
+#define PTS_REQ_FUNC_COMP_EVID_H_
+
+typedef enum pts_req_func_comp_evid_t pts_req_func_comp_evid_t;
+
+#include <library.h>
+
+/**
+ * PTS Request Functional Component Evidence Flags
+ */
+enum pts_req_func_comp_evid_t {
+ /** Transitive Trust Chain flag */
+ PTS_REQ_FUNC_COMP_EVID_TTC = (1<<7),
+ /** Verify Component flag */
+ PTS_REQ_FUNC_COMP_EVID_VER = (1<<6),
+ /** Current Evidence flag */
+ PTS_REQ_FUNC_COMP_EVID_CURR = (1<<5),
+ /** PCR Information flag */
+ PTS_REQ_FUNC_COMP_EVID_PCR = (1<<4),
+};
+
+#endif /** PTS_FUNCT_COMP_EVID_REQ_H_ @}*/
diff --git a/src/libpts/pts/pts_simple_evid_final.h b/src/libpts/pts/pts_simple_evid_final.h
new file mode 100644
index 000000000..0c8dea0cc
--- /dev/null
+++ b/src/libpts/pts/pts_simple_evid_final.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Sansar Choinyambuu
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pts_simple_evid_final pts_rsimple_evid_final
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_SIMPLE_EVID_FINAL_H_
+#define PTS_SIMPLE_EVID_FINAL_H_
+
+typedef enum pts_simple_evid_final_flag_t pts_simple_evid_final_flag_t;
+
+#include <library.h>
+
+/**
+ * PTS Simple Evidence Final Flags
+ */
+enum pts_simple_evid_final_flag_t {
+ /** TPM PCR Composite and TPM Quote Signature not included */
+ PTS_SIMPLE_EVID_FINAL_NO = 0x00,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO = 0x40,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO not appended */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 = 0x80,
+ /** TPM PCR Composite and TPM Quote Signature included
+ * using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO appended */
+ PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER = 0xC0,
+ /** Evidence Signature included */
+ PTS_SIMPLE_EVID_FINAL_EVID_SIG = 0x20,
+};
+
+#endif /** PTS_SIMPLE_EVID_FINAL_H_ @}*/