diff options
Diffstat (limited to 'src/libpts/pts')
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","e_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_ @}*/ |