diff options
author | Romain Francoise <rfrancoise@debian.org> | 2014-10-21 19:28:38 +0200 |
---|---|---|
committer | Romain Francoise <rfrancoise@debian.org> | 2014-10-21 19:28:38 +0200 |
commit | 2b8de74ff4c334c25e89988c4a401b24b5bcf03d (patch) | |
tree | 10fb49ca94bfd0c8b8a583412281abfc0186836e /src/libimcv/pts/components/ita | |
parent | 81c63b0eed39432878f78727f60a1e7499645199 (diff) | |
download | vyos-strongswan-2b8de74ff4c334c25e89988c4a401b24b5bcf03d.tar.gz vyos-strongswan-2b8de74ff4c334c25e89988c4a401b24b5bcf03d.zip |
Import upstream release 5.2.1
Diffstat (limited to 'src/libimcv/pts/components/ita')
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_func_name.c | 45 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_func_name.h | 85 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_ima.c | 914 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_ima.h | 35 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_tboot.c | 362 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_tboot.h | 35 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_tgrub.c | 208 | ||||
-rw-r--r-- | src/libimcv/pts/components/ita/ita_comp_tgrub.h | 35 |
8 files changed, 1719 insertions, 0 deletions
diff --git a/src/libimcv/pts/components/ita/ita_comp_func_name.c b/src/libimcv/pts/components/ita/ita_comp_func_name.c new file mode 100644 index 000000000..a593281ba --- /dev/null +++ b/src/libimcv/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/libimcv/pts/components/ita/ita_comp_func_name.h b/src/libimcv/pts/components/ita/ita_comp_func_name.h new file mode 100644 index 000000000..eb2f363f3 --- /dev/null +++ b/src/libimcv/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/libimcv/pts/components/ita/ita_comp_ima.c b/src/libimcv/pts/components/ita/ita_comp_ima.c new file mode 100644 index 000000000..3f92b04b1 --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_ima.c @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2011-2014 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 "imcv.h" +#include "pts/pts_pcr.h" +#include "pts/pts_ima_bios_list.h" +#include "pts/pts_ima_event_list.h" +#include "pts/components/pts_component.h" + +#include <utils/debug.h> +#include <crypto/hashers/hasher.h> +#include <pen/pen.h> + +#define SECURITY_DIR "/sys/kernel/security/" +#define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements" +#define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements" +#define IMA_FILENAME_LEN_MAX 255 + +typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t; +typedef enum ima_state_t ima_state_t; + +enum ima_state_t { + IMA_STATE_INIT, + IMA_STATE_BIOS, + IMA_STATE_BOOT_AGGREGATE, + IMA_STATE_RUNTIME, + IMA_STATE_END +}; + +/** + * Private data of a pts_ita_comp_ima_t object. + * + */ +struct pts_ita_comp_ima_t { + + /** + * Public pts_component_t interface. + */ + pts_component_t public; + + /** + * Component Functional Name + */ + pts_comp_func_name_t *name; + + /** + * Sub-component depth + */ + uint32_t depth; + + /** + * PTS measurement database + */ + pts_database_t *pts_db; + + /** + * Primary key for AIK database entry + */ + int aik_id; + + /** + * Primary key for IMA BIOS Component Functional Name database entry + */ + int bios_cid; + + /** + * Primary key for IMA Runtime Component Functional Name database entry + */ + int ima_cid; + + /** + * Component is registering IMA BIOS measurements + */ + bool is_bios_registering; + + /** + * Component is registering IMA boot aggregate measurement + */ + bool is_ima_registering; + + /** + * Measurement sequence number + */ + int seq_no; + + /** + * Expected IMA BIOS measurement count + */ + int bios_count; + + /** + * IMA BIOS measurements + */ + pts_ima_bios_list_t *bios_list; + + /** + * IMA runtime file measurements + */ + pts_ima_event_list_t *ima_list; + + /** + * Whether to send pcr_before and pcr_after info + */ + bool pcr_info; + + /** + * Creation time of measurement + */ + time_t creation_time; + + /** + * IMA state machine + */ + ima_state_t state; + + /** + * Total number of component measurements + */ + int count; + + /** + * Number of successful component measurements + */ + int count_ok; + + /** + * Number of unknown component measurements + */ + int count_unknown; + + /** + * Number of differing component measurements + */ + int count_differ; + + /** + * Number of failed component measurements + */ + int count_failed; + + /** + * Reference count + */ + refcount_t ref; + +}; + +/** + * Extend measurement into PCR and create evidence + */ +static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, + uint8_t qualifier, pts_pcr_t *pcrs, + uint32_t pcr, chunk_t measurement) +{ + size_t pcr_len; + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; + pts_comp_func_name_t *name; + pts_comp_evidence_t *evidence; + chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty; + + hash_algo = PTS_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; + pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); + + if (this->pcr_info) + { + pcr_before = chunk_clone(pcrs->get(pcrs, pcr)); + } + pcr_after = pcrs->extend(pcrs, pcr, measurement); + if (!pcr_after.ptr) + { + free(pcr_before.ptr); + return NULL; + } + name = this->name->clone(this->name); + name->set_qualifier(name, qualifier); + evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo, + pcr_transform, this->creation_time, measurement); + if (this->pcr_info) + { + pcr_after =chunk_clone(pcrs->get(pcrs, pcr)); + evidence->set_pcr_info(evidence, pcr_before, pcr_after); + } + return evidence; +} + +/** + * Generate an IMA or IMA-NG hash from an event digest and event name + * + * @param digest event digest + * @param ima_algo hash algorithm string ("sha1:", "sha256:", etc.) + * @param ima_name event name + * @param little_endian endianness of client platform + * @param algo hash algorithm used by TPM + * @param hash_buf hash value to be compared with TPM measurement + */ +static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name, + bool little_endian, pts_meas_algorithms_t algo, + char *hash_buf) +{ + hash_algorithm_t hash_alg; + hasher_t *hasher; + bool success; + + hash_alg = pts_meas_algo_to_hash(algo); + hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); + if (!hasher) + { + DBG1(DBG_PTS, "%N hasher could not be created", + hash_algorithm_short_names, hash_alg); + return FALSE; + } + + if (ima_algo) + { + uint32_t d_len, n_len; + chunk_t algo_name, event_name, digest_len, name_len; + + /* IMA-NG hash */ + algo_name = chunk_create(ima_algo, strlen(ima_algo) + 1); + event_name = chunk_create(ima_name, strlen(ima_name) + 1); + + d_len = algo_name.len + digest.len; + digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len)); + /* TODO handle endianness of both client and server platforms */ + + n_len = event_name.len; + name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len)); + /* TODO handle endianness of both client and server platforms */ + + success = hasher->get_hash(hasher, digest_len, NULL) && + hasher->get_hash(hasher, algo_name, NULL) && + hasher->get_hash(hasher, digest, NULL) && + hasher->get_hash(hasher, name_len, NULL) && + hasher->get_hash(hasher, event_name, hash_buf); + } + else + { + u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1]; + chunk_t file_name; + + /* IMA legacy hash */ + memset(filename_buffer, 0, sizeof(filename_buffer)); + strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX); + file_name = chunk_create (filename_buffer, sizeof(filename_buffer)); + + success = hasher->get_hash(hasher, digest, NULL) && + hasher->get_hash(hasher, file_name, hash_buf); + } + hasher->destroy(hasher); + + return success; +} + +/** + * Compute and check boot aggregate value by hashing PCR0 to PCR7 + */ +static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement, + char *algo) +{ + u_char pcr_buffer[HASH_SIZE_SHA1]; + chunk_t boot_aggregate; + hasher_t *hasher; + uint32_t i; + bool success, pcr_ok = TRUE; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher) + { + DBG1(DBG_PTS, "%N hasher could not be created", + hash_algorithm_short_names, HASH_SHA1); + return FALSE; + } + for (i = 0; i < 8 && pcr_ok; i++) + { + pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL); + } + if (pcr_ok) + { + pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer); + } + hasher->destroy(hasher); + + if (pcr_ok) + { + boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer)); + + /* TODO handle endianness of client platform */ + pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate", + TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer); + } + if (pcr_ok) + { + success = chunk_equals(boot_aggregate, measurement); + DBG1(DBG_PTS, "boot aggregate value is %scorrect", + success ? "":"in"); + return success; + } + else + { + DBG1(DBG_PTS, "failed to compute boot aggregate value"); + return FALSE; + } +} + +METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*, + pts_ita_comp_ima_t *this) +{ + return this->name; +} + +METHOD(pts_component_t, get_evidence_flags, uint8_t, + pts_ita_comp_ima_t *this) +{ + return PTS_REQ_FUNC_COMP_EVID_PCR; +} + +METHOD(pts_component_t, get_depth, uint32_t, + pts_ita_comp_ima_t *this) +{ + return this->depth; +} + +METHOD(pts_component_t, measure, status_t, + pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts, + pts_comp_evidence_t **evidence) +{ + pts_pcr_t *pcrs; + pts_comp_evidence_t *evid = NULL; + size_t algo_len, name_len; + chunk_t measurement; + char *uri, *algo, *name; + uint32_t pcr; + status_t status; + + pcrs = pts->get_pcrs(pts); + + if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_TRUSTED)) + { + switch (this->state) + { + case IMA_STATE_INIT: + this->bios_list = pts_ima_bios_list_create( + IMA_BIOS_MEASUREMENTS); + if (!this->bios_list) + { + return FAILED; + } + this->creation_time = this->bios_list->get_time(this->bios_list); + this->bios_count = this->bios_list->get_count(this->bios_list); + this->state = IMA_STATE_BIOS; + /* fall through to next state */ + case IMA_STATE_BIOS: + status = this->bios_list->get_next(this->bios_list, &pcr, + &measurement); + if (status != SUCCESS) + { + DBG1(DBG_PTS, "could not retrieve bios measurement entry"); + return status; + } + evid = extend_pcr(this, qualifier, pcrs, pcr, measurement); + + this->state = this->bios_list->get_count(this->bios_list) ? + IMA_STATE_BIOS : IMA_STATE_INIT; + break; + default: + return FAILED; + } + } + else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_OS)) + { + switch (this->state) + { + case IMA_STATE_INIT: + this->ima_list = pts_ima_event_list_create( + IMA_RUNTIME_MEASUREMENTS); + if (!this->ima_list) + { + return FAILED; + } + this->creation_time = this->ima_list->get_time(this->ima_list); + this->count = this->ima_list->get_count(this->ima_list); + this->state = IMA_STATE_BOOT_AGGREGATE; + /* fall through to next state */ + case IMA_STATE_BOOT_AGGREGATE: + case IMA_STATE_RUNTIME: + status = this->ima_list->get_next(this->ima_list, &measurement, + &algo, &name); + if (status != SUCCESS) + { + DBG1(DBG_PTS, "could not retrieve ima measurement entry"); + return status; + } + if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count) + { + if (!check_boot_aggregate(pcrs, measurement, algo)) + { + return FAILED; + } + } + evid = extend_pcr(this, qualifier, pcrs, IMA_PCR, + measurement); + if (evid) + { + if (algo) + { + algo_len = strlen(algo); + name_len = strlen(name); + uri = malloc(algo_len + name_len + 1); + memcpy(uri, algo, algo_len); + strcpy(uri + algo_len, name); + } + else + { + uri = strdup(name); + } + evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED, + uri); + free(uri); + } + free(name); + free(algo); + + this->state = this->ima_list->get_count(this->ima_list) ? + IMA_STATE_RUNTIME : IMA_STATE_END; + break; + default: + return FAILED; + } + } + else + { + DBG1(DBG_PTS, "unsupported functional component name qualifier"); + return FAILED; + } + + *evidence = evid; + if (!evid) + { + return FAILED; + } + + return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ? + SUCCESS : NEED_MORE; +} + +/** + * Parse a validation URI of the form <hash algorithm>:<event name> + * into its components + */ +static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence, + char **ima_name, char **ima_algo, char *algo_buf) +{ + pts_meas_algorithms_t hash_algo; + char *uri, *pos, *algo, *name; + + evidence->get_validation(evidence, &uri); + + /* IMA-NG format? */ + pos = strchr(uri, ':'); + if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX) + { + memset(algo_buf, '\0', IMA_ALGO_LEN_MAX); + memcpy(algo_buf, uri, pos - uri + 1); + algo = algo_buf; + name = pos + 1; + + if (streq(algo, "sha1:") || streq(algo, ":")) + { + hash_algo = PTS_MEAS_ALGO_SHA1; + } + else if (streq(algo, "sha256:")) + { + hash_algo = PTS_MEAS_ALGO_SHA256; + } + else if (streq(algo, "sha384:")) + { + hash_algo = PTS_MEAS_ALGO_SHA384; + } + else + { + hash_algo = PTS_MEAS_ALGO_NONE; + } + } + else + { + algo = NULL; + name = uri; + hash_algo = PTS_MEAS_ALGO_SHA1; + } + + if (ima_name) + { + *ima_name = name; + } + if (ima_algo) + { + *ima_algo = algo; + } + + return hash_algo; +} + +METHOD(pts_component_t, verify, status_t, + pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts, + pts_comp_evidence_t *evidence) +{ + bool has_pcr_info; + uint32_t pcr; + pts_meas_algorithms_t algo; + pts_pcr_transform_t transform; + pts_pcr_t *pcrs; + time_t creation_time; + chunk_t measurement, pcr_before, pcr_after; + status_t status = NOT_FOUND; + + this->aik_id = pts->get_aik_id(pts); + pcrs = pts->get_pcrs(pts); + measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform, + &creation_time); + + if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_TRUSTED)) + { + switch (this->state) + { + case IMA_STATE_INIT: + this->name->set_qualifier(this->name, qualifier); + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->aik_id, algo, + &this->bios_cid, &this->bios_count); + this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN); + if (status != SUCCESS) + { + return status; + } + + if (this->bios_count) + { + DBG1(DBG_PTS, "checking %d BIOS evidence measurements", + this->bios_count); + } + else + { + DBG1(DBG_PTS, "registering BIOS evidence measurements"); + this->is_bios_registering = TRUE; + } + + this->state = IMA_STATE_BIOS; + /* fall through to next state */ + case IMA_STATE_BIOS: + if (this->is_bios_registering) + { + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->bios_cid, this->aik_id, + ++this->seq_no, pcr, algo); + if (status != SUCCESS) + { + return status; + } + this->bios_count = this->seq_no + 1; + } + else + { + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->bios_cid, this->aik_id, + ++this->seq_no, pcr, algo); + if (status == FAILED) + { + return status; + } + } + break; + default: + return FAILED; + } + } + else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_OS)) + { + int ima_count; + char *ima_algo, *ima_name; + char algo_buf[IMA_ALGO_LEN_MAX]; + pts_meas_algorithms_t hash_algo; + + hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo, + algo_buf); + + switch (this->state) + { + case IMA_STATE_BIOS: + this->state = IMA_STATE_RUNTIME; + + if (!streq(ima_name, "boot_aggregate")) + { + DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' " + "but is '%s'", ima_name); + return FAILED; + } + if (hash_algo != PTS_MEAS_ALGO_SHA1) + { + DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N " + "but is %N", + pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, + pts_meas_algorithm_names, hash_algo); + return FAILED; + } + if (!check_boot_aggregate(pcrs, measurement, ima_algo)) + { + return FAILED; + } + this->state = IMA_STATE_INIT; + /* fall through to next state */ + case IMA_STATE_INIT: + this->name->set_qualifier(this->name, qualifier); + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->aik_id, algo, + &this->ima_cid, &ima_count); + this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN); + if (status != SUCCESS) + { + return status; + } + + if (ima_count) + { + DBG1(DBG_PTS, "checking boot aggregate evidence " + "measurement"); + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->ima_cid, + this->aik_id, 1, pcr, algo); + } + else + { + DBG1(DBG_PTS, "registering boot aggregate evidence " + "measurement"); + this->is_ima_registering = TRUE; + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->ima_cid, + this->aik_id, 1, pcr, algo); + } + this->state = IMA_STATE_RUNTIME; + + if (status != SUCCESS) + { + return status; + } + break; + case IMA_STATE_RUNTIME: + { + uint8_t hash_buf[HASH_SIZE_SHA512]; + chunk_t digest, hash; + enumerator_t *e; + + this->count++; + if (evidence->get_validation(evidence, NULL) != + PTS_COMP_EVID_VALIDATION_PASSED) + { + DBG1(DBG_PTS, "evidence validation failed"); + this->count_failed++; + return FAILED; + } + hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo)); + + e = this->pts_db->create_file_meas_enumerator(this->pts_db, + pts->get_platform_id(pts), + hash_algo, ima_name); + if (e) + { + while (e->enumerate(e, &digest)) + { + if (!ima_hash(digest, ima_algo, ima_name, + FALSE, algo, hash_buf)) + { + status = FAILED; + break; + } + if (chunk_equals(measurement, hash)) + { + status = SUCCESS; + break; + } + else + { + status = VERIFY_ERROR; + } + } + e->destroy(e); + } + else + { + status = FAILED; + } + + switch (status) + { + case SUCCESS: + DBG3(DBG_PTS, "%#B for '%s' is ok", + &measurement, ima_name); + this->count_ok++; + break; + case NOT_FOUND: + DBG2(DBG_PTS, "%#B for '%s' not found", + &measurement, ima_name); + this->count_unknown++; + break; + case VERIFY_ERROR: + DBG1(DBG_PTS, "%#B for '%s' differs", + &measurement, ima_name); + this->count_differ++; + break; + case FAILED: + default: + DBG1(DBG_PTS, "%#B for '%s' failed", + &measurement, ima_name); + this->count_failed++; + } + break; + } + default: + return FAILED; + } + } + else + { + DBG1(DBG_PTS, "unsupported functional component name qualifier"); + return FAILED; + } + + has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); + if (has_pcr_info) + { + if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr))) + { + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value", + pcr); + } + if (pcrs->set(pcrs, pcr, pcr_after)) + { + return status; + } + } + else + { + pcr_after = pcrs->extend(pcrs, pcr, measurement); + if (pcr_after.ptr) + { + return status; + } + } + return FAILED; +} + +METHOD(pts_component_t, finalize, bool, + pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result) +{ + char result_buf[BUF_LEN]; + char *pos = result_buf; + size_t len = BUF_LEN; + int written; + bool success = TRUE; + + this->name->set_qualifier(this->name, qualifier); + + if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_TRUSTED)) + { + /* finalize BIOS measurements */ + if (this->is_bios_registering) + { + /* close registration */ + this->is_bios_registering = FALSE; + + snprintf(pos, len, "registered %d BIOS evidence measurements", + this->seq_no); + } + else if (this->seq_no < this->bios_count) + { + snprintf(pos, len, "%d of %d BIOS evidence measurements missing", + this->bios_count - this->seq_no, this->bios_count); + success = FALSE; + } + else + { + snprintf(pos, len, "%d BIOS evidence measurements are ok", + this->bios_count); + } + } + else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_OS)) + { + /* finalize IMA file measurements */ + if (this->is_ima_registering) + { + /* close registration */ + this->is_ima_registering = FALSE; + + written = snprintf(pos, len, "registered IMA boot aggregate " + "evidence measurement; "); + pos += written; + len -= written; + } + if (this->count) + { + snprintf(pos, len, "processed %d IMA file evidence measurements: " + "%d ok, %d unknown, %d differ, %d failed", + this->count, this->count_ok, this->count_unknown, + this->count_differ, this->count_failed); + } + else + { + snprintf(pos, len, "no IMA file evidence measurements"); + success = FALSE; + } + } + else + { + snprintf(pos, len, "unsupported functional component name qualifier"); + success = FALSE; + } + this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN); + + DBG1(DBG_PTS, "%s", result_buf); + result->write_data(result, chunk_from_str(result_buf)); + + return success; +} + +METHOD(pts_component_t, get_ref, pts_component_t*, + pts_ita_comp_ima_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +METHOD(pts_component_t, destroy, void, + pts_ita_comp_ima_t *this) +{ + int count; + + if (ref_put(&this->ref)) + { + + if (this->is_bios_registering) + { + count = this->pts_db->delete_comp_measurements(this->pts_db, + this->bios_cid, this->aik_id); + DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements", + count); + } + if (this->is_ima_registering) + { + count = this->pts_db->delete_comp_measurements(this->pts_db, + this->ima_cid, this->aik_id); + DBG1(DBG_PTS, "deleted registered boot aggregate evidence " + "measurement"); + } + DESTROY_IF(this->bios_list); + DESTROY_IF(this->ima_list); + this->name->destroy(this->name); + + free(this); + } +} + +/** + * See header + */ +pts_component_t *pts_ita_comp_ima_create(uint32_t depth, + pts_database_t *pts_db) +{ + pts_ita_comp_ima_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, + .finalize = _finalize, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA, + PTS_QUALIFIER_UNKNOWN), + .depth = depth, + .pts_db = pts_db, + .pcr_info = lib->settings->get_bool(lib->settings, + "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns), + .ref = 1, + ); + + return &this->public; +} + diff --git a/src/libimcv/pts/components/ita/ita_comp_ima.h b/src/libimcv/pts/components/ita/ita_comp_ima.h new file mode 100644 index 000000000..546d0a4b2 --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_ima.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011-2012 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 depth Sub-component depth + * @param pts_db PTS measurement database + */ +pts_component_t* pts_ita_comp_ima_create(u_int32_t depth, + pts_database_t *pts_db); + +#endif /** PTS_ITA_COMP_IMA_H_ @}*/ diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.c b/src/libimcv/pts/components/ita/ita_comp_tboot.c new file mode 100644 index 000000000..273c18f31 --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_tboot.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2011-2014 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 "imcv.h" +#include "pts/components/pts_component.h" + +#include <utils/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; + + /** + * Sub-component depth + */ + u_int32_t depth; + + /** + * PTS measurement database + */ + pts_database_t *pts_db; + + /** + * Primary key for AIK database entry + */ + int aik_id; + + /** + * 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; + + /** + * Reference count + */ + refcount_t ref; + +}; + +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, u_int8_t qualifier, pts_t *pts, + pts_comp_evidence_t **evidence) + +{ + size_t pcr_len; + pts_pcr_t *pcrs; + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; + pts_comp_evidence_t *evid; + char *meas_hex, *pcr_before_hex, *pcr_after_hex; + chunk_t measurement, pcr_before, pcr_after; + u_int32_t extended_pcr; + + 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, + "%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns); + pcr_before_hex = lib->settings->get_str(lib->settings, + "%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns); + pcr_after_hex = lib->settings->get_str(lib->settings, + "%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns); + 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, + "%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns); + pcr_before_hex = lib->settings->get_str(lib->settings, + "%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns); + pcr_after_hex = lib->settings->get_str(lib->settings, + "%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns); + 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_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; + pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); + + /* get and check the measurement data */ + 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 != pcr_len) + { + DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size"); + free(measurement.ptr); + free(pcr_before.ptr); + free(pcr_after.ptr); + return FAILED; + } + + pcrs = pts->get_pcrs(pts); + pcrs->set(pcrs, extended_pcr, pcr_after); + evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name), + this->depth, extended_pcr, hash_algo, pcr_transform, + this->measurement_time, measurement); + 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, u_int8_t qualifier,pts_t *pts, + pts_comp_evidence_t *evidence) +{ + bool has_pcr_info; + u_int32_t extended_pcr, vid, name; + enum_name_t *names; + pts_meas_algorithms_t algo; + pts_pcr_transform_t transform; + pts_pcr_t *pcrs; + time_t measurement_time; + chunk_t measurement, pcr_before, pcr_after; + status_t status; + + this->aik_id = pts->get_aik_id(pts); + pcrs = pts->get_pcrs(pts); + measurement = evidence->get_measurement(evidence, &extended_pcr, + &algo, &transform, &measurement_time); + + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->aik_id, algo, + &this->cid, &this->count); + if (status != SUCCESS) + { + return status; + } + vid = this->name->get_vendor_id(this->name); + name = this->name->get_name(this->name); + names = imcv_pts_components->get_comp_func_names(imcv_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) + { + status = this->pts_db->insert_comp_measurement(this->pts_db, + measurement, this->cid, this->aik_id, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } + this->count = this->seq_no + 1; + } + else + { + status = this->pts_db->check_comp_measurement(this->pts_db, + measurement, this->cid, this->kid, + ++this->seq_no, extended_pcr, algo); + if (status != SUCCESS) + { + return status; + } + } + + has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); + if (has_pcr_info) + { + if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr))) + { + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value", + extended_pcr); + } + if (pcrs->set(pcrs, extended_pcr, pcr_after)) + { + return SUCCESS; + } + } + + return SUCCESS; +} + +METHOD(pts_component_t, finalize, bool, + pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result) +{ + char result_buf[BUF_LEN]; + + if (this->is_registering) + { + /* close registration */ + this->is_registering = FALSE; + + snprintf(result_buf, BUF_LEN, "registered %d evidence measurements", + this->seq_no); + } + else if (this->seq_no < this->count) + { + snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements " + "missing", this->count - this->seq_no, this->count); + return FALSE; + } + else + { + snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok", + this->count); + } + DBG1(DBG_PTS, "%s", result_buf); + result->write_data(result, chunk_from_str(result_buf)); + + return TRUE; +} + +METHOD(pts_component_t, get_ref, pts_component_t*, + pts_ita_comp_tboot_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +METHOD(pts_component_t, destroy, void, + pts_ita_comp_tboot_t *this) +{ + int count; + u_int32_t vid, name; + enum_name_t *names; + + if (ref_put(&this->ref)) + { + if (this->is_registering) + { + count = this->pts_db->delete_comp_measurements(this->pts_db, + this->cid, this->aik_id); + vid = this->name->get_vendor_id(this->name); + name = this->name->get_name(this->name); + names = imcv_pts_components->get_comp_func_names(imcv_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); + } +} + +/** + * See header + */ +pts_component_t *pts_ita_comp_tboot_create(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, + .finalize = _finalize, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT, + PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_TRUSTED), + .depth = depth, + .pts_db = pts_db, + .ref = 1, + ); + + return &this->public; +} + diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.h b/src/libimcv/pts/components/ita/ita_comp_tboot.h new file mode 100644 index 000000000..1e1a14831 --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_tboot.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * 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 depth Sub-component depth + * @param pts_db PTS measurement database + */ +pts_component_t* pts_ita_comp_tboot_create(u_int32_t depth, + pts_database_t *pts_db); + +#endif /** PTS_ITA_COMP_TBOOT_H_ @}*/ diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.c b/src/libimcv/pts/components/ita/ita_comp_tgrub.c new file mode 100644 index 000000000..097e4c89c --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2011-2012 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 <utils/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; + + /** + * Reference count + */ + refcount_t ref; + +}; + +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, u_int8_t qualifier, pts_t *pts, + pts_comp_evidence_t **evidence) +{ + size_t pcr_len; + pts_pcr_transform_t pcr_transform; + pts_meas_algorithms_t hash_algo; + pts_comp_evidence_t *evid; + u_int32_t extended_pcr; + time_t measurement_time; + chunk_t measurement, pcr_before, pcr_after; + + /* 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_MEAS_ALGO_SHA1; + pcr_len = HASH_SIZE_SHA1; + pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); + + measurement = chunk_alloc(pcr_len); + 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, u_int8_t qualifier, pts_t *pts, + pts_comp_evidence_t *evidence) +{ + bool has_pcr_info; + u_int32_t extended_pcr; + pts_meas_algorithms_t algo; + pts_pcr_transform_t transform; + pts_pcr_t *pcrs; + time_t measurement_time; + chunk_t pcr_before, pcr_after; + chunk_t measurement __attribute__((unused)); + + pcrs = pts->get_pcrs(pts); + 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 (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr))) + { + DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value"); + } + if (pcrs->set(pcrs, extended_pcr, pcr_after)) + { + return SUCCESS; + } + } + + return SUCCESS; +} + +METHOD(pts_component_t, finalize, bool, + pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result) +{ + return FALSE; +} + +METHOD(pts_component_t, get_ref, pts_component_t*, + pts_ita_comp_tgrub_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +METHOD(pts_component_t, destroy, void, + pts_ita_comp_tgrub_t *this) +{ + if (ref_put(&this->ref)) + { + this->name->destroy(this->name); + free(this); + } +} + +/** + * See header + */ +pts_component_t *pts_ita_comp_tgrub_create(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, + .finalize = _finalize, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB, + PTS_ITA_QUALIFIER_FLAG_KERNEL | + PTS_ITA_QUALIFIER_TYPE_TRUSTED), + .depth = depth, + .pts_db = pts_db, + .ref = 1, + ); + + return &this->public; +} diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.h b/src/libimcv/pts/components/ita/ita_comp_tgrub.h new file mode 100644 index 000000000..59913c82d --- /dev/null +++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * 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 depth Sub-component depth + * @param pts_db PTS measurement database + */ +pts_component_t* pts_ita_comp_tgrub_create(u_int32_t depth, + pts_database_t *pts_db); + +#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/ |