Merged libpts into libimcv

This commit is contained in:
Andreas Steffen
2014-10-05 12:55:37 +02:00
parent c4d0987609
commit d6fb2cc6e3
159 changed files with 232 additions and 439 deletions
@@ -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"
);
@@ -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_ @}*/
@@ -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;
}
@@ -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_ @}*/
@@ -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;
}
@@ -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_ @}*/
@@ -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;
}
@@ -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_ @}*/
@@ -0,0 +1,255 @@
/*
* 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 <utils/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
*/
char *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;
DBG3(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
DBG3(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
}
METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
private_pts_comp_evidence_t *this, char **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,
char *uri)
{
this->validation = validation;
if (uri)
{
this->policy_uri = strdup(uri);
DBG3(DBG_PTS, "'%s'", 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);
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, "");
DBG3(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
DBG3(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;
}
@@ -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,
char **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, char* 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_ @}*/
@@ -0,0 +1,162 @@
/*
* 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 "imcv.h"
#include "pts/components/pts_comp_func_name.h"
#include <utils/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;
}
METHOD(pts_comp_func_name_t, set_qualifier, void,
private_pts_comp_func_name_t *this, u_int8_t qualifier)
{
this->qualifier = qualifier;
}
static bool equals(private_pts_comp_func_name_t *this,
private_pts_comp_func_name_t *other)
{
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 = imcv_pts_components->get_comp_func_names(imcv_pts_components,
this->vid);
types = imcv_pts_components->get_qualifier_type_names(imcv_pts_components,
this->vid);
type = imcv_pts_components->get_qualifier(imcv_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,
.set_qualifier = _set_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;
}
@@ -0,0 +1,103 @@
/*
* 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_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);
/**
* Set the PTS Component Functional Name Qualifier
*
* @param qualifier PTS Component Functional Name Qualifier to be set
*/
void (*set_qualifier)(pts_comp_func_name_t *this, u_int8_t qualifier);
/**
* Check to PTS Component Functional Names for equality
*
* @param other Other PTS Component Functional Name
* @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 qualifier 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_ @}*/
+109
View File
@@ -0,0 +1,109 @@
/*
* 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_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/pts_file_meas.h"
#include "pts/components/pts_comp_func_name.h"
#include "pts/components/pts_comp_evidence.h"
#include <library.h>
#include <bio/bio_writer.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 qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence returns component evidence measureemt
* @param measurements additional file measurements (NULL if not present)
* @return status return code
*/
status_t (*measure)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t** evidence);
/**
* Verify the evidence measurements of the PTS Functional Component
*
* @param qualifier PTS Component Functional Name Qualifier
* @param pts PTS interface
* @param evidence component evidence measurement to be verified
* @return status return code
*/
status_t (*verify)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
pts_comp_evidence_t *evidence);
/**
* Tell the PTS Functional Component to finalize pending registrations
* and check for missing measurements
*
* @param qualifier PTS Component Functional Name Qualifier
* @param result writer appending concise measurement result
* @return TRUE if finalization successful
*/
bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
bio_writer_t *result);
/**
* Get a new reference to the PTS Functional Component
*
* @return this, with an increased refcount
*/
pts_component_t* (*get_ref)(pts_component_t *this);
/**
* Destroys a pts_component_t object.
*/
void (*destroy)(pts_component_t *this);
};
#endif /** PTS_COMPONENT_H_ @}*/
@@ -0,0 +1,315 @@
/*
* 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 "pts/components/pts_component_manager.h"
#include <collections/linked_list.h>
#include <utils/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(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;
}
@@ -0,0 +1,124 @@
/*
* 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_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_ @}*/
@@ -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"
);
@@ -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_ @}*/
File diff suppressed because it is too large Load Diff
+315
View File
@@ -0,0 +1,315 @@
/*
* Copyright (C) 2011 Sansar Choinyambuu
* Copyright (C) 2012-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.
*/
/**
* @defgroup pts pts
* @{ @ingroup libpts
*/
#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_pcr.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 <collections/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 primary key of platform entry in database
*
* @return Platform and OS info
*/
int (*get_platform_id)(pts_t *this);
/**
* Set primary key of platform entry in database
*
* @param pid Primary key of platform entry in database
*/
void (*set_platform_id)(pts_t *this, int pid);
/**
* 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 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
* @param aik_id Primary key referencing AIK in database
*/
void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id);
/**
* Get primary key referencing AIK in database
*
* @return Primary key referencing AIK in database
*/
int (*get_aik_id)(pts_t *this);
/**
* 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);
/**
* Obtain file metadata
*
* @param pathname Absolute pathname of file/directory
* @param is_dir 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_dir);
/**
* 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);
/**
* Get the shadow PCR set
*
* @return shadow PCR set
*/
pts_pcr_t* (*get_pcrs)(pts_t *this);
/**
* 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_ @}*/
+136
View File
@@ -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 <utils/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;
}
+55
View File
@@ -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_ @}*/
+432
View File
@@ -0,0 +1,432 @@
/*
* Copyright (C) 2011-2012 Sansar Choinyambuu
* Copyright (C) 2012-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.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <libgen.h>
#include "pts_database.h"
#include <utils/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, get_pathname, char*,
private_pts_database_t *this, bool is_dir, int id)
{
enumerator_t *e;
char *path, *name, *sep, *pathname = NULL;
if (is_dir)
{
e = this->db->query(this->db,
"SELECT path FROM directories WHERE id = ?",
DB_INT, id, DB_TEXT);
if (!e || !e->enumerate(e, &path))
{
pathname = NULL;
}
else
{
pathname = strdup(path);
}
}
else
{
e = this->db->query(this->db,
"SELECT d.path, f.name FROM files AS f "
"JOIN directories AS d ON d.id = f.dir WHERE f.id = ?",
DB_INT, id, DB_TEXT, DB_TEXT);
if (e && e->enumerate(e, &path, &name))
{
if (path[0] == '/')
{ /* Unix style absolute path */
sep = "/";
}
else
{ /* Windows absolute path */
sep = "\\";
}
if (asprintf(&pathname, "%s%s%s",
path, streq(path, "/") ? "" : sep, name) == -1)
{
pathname = NULL;
}
}
}
DESTROY_IF(e);
return pathname;
}
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
bool is_dir, int id)
{
enumerator_t *e;
if (is_dir)
{
e = this->db->query(this->db,
"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"JOIN directories as d ON d.id = f.dir "
"WHERE fh.product = ? AND fh.algo = ? AND d.id = ? "
"ORDER BY f.name",
DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
}
else
{
e = this->db->query(this->db,
"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
}
return e;
}
METHOD(pts_database_t, add_file_measurement, status_t,
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
chunk_t measurement, char *filename, bool is_dir, int id)
{
enumerator_t *e;
char *name;
chunk_t hash_value;
int hash_id, fid;
status_t status = SUCCESS;
if (is_dir)
{
/* does filename entry already exist? */
e = this->db->query(this->db,
"SELECT id FROM files WHERE name = ? AND dir = ?",
DB_TEXT, filename, DB_INT, id, DB_INT);
if (!e)
{
return FAILED;
}
if (!e->enumerate(e, &fid))
{
/* create filename entry */
if (this->db->execute(this->db, &fid,
"INSERT INTO files (name, dir) VALUES (?, ?)",
DB_TEXT, filename, DB_INT, id) != 1)
{
DBG1(DBG_PTS, "could not insert filename into database");
status = FAILED;
}
}
e->destroy(e);
}
else
{
fid = id;
/* verify filename */
e = this->db->query(this->db,
"SELECT name FROM files WHERE id = ?", DB_INT, fid, DB_TEXT);
if (!e)
{
return FAILED;
}
if (!e->enumerate(e, &name) || !streq(name, filename))
{
DBG1(DBG_PTS, "filename of reference measurement does not match");
status = FAILED;
}
e->destroy(e);
}
if (status != SUCCESS)
{
return status;
}
/* does hash measurement value already exist? */
e = this->db->query(this->db,
"SELECT fh.id, fh.hash FROM file_hashes AS fh "
"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
DB_INT, pid, DB_INT, algo, DB_INT, fid, DB_INT, DB_BLOB);
if (!e)
{
return FAILED;
}
if (e->enumerate(e, &hash_id, &hash_value))
{
if (!chunk_equals(measurement, hash_value))
{
/* update hash measurement value */
if (this->db->execute(this->db, &hash_id,
"UPDATE file_hashes SET hash = ? WHERE id = ?",
DB_BLOB, measurement, DB_INT, hash_id) != 1)
{
status = FAILED;
}
}
}
else
{
/* insert hash measurement value */
if (this->db->execute(this->db, &hash_id,
"INSERT INTO file_hashes (file, product, algo, hash) "
"VALUES (?, ?, ?, ?)", DB_INT, fid, DB_INT, pid,
DB_INT, algo, DB_BLOB, measurement) != 1)
{
status = FAILED;
}
}
e->destroy(e);
return status;
}
METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
char *filename)
{
enumerator_t *e;
char *dir, *file;
if (strlen(filename) < 1)
{
return NULL;
}
/* separate filename into directory and basename components */
dir = path_dirname(filename);
file = path_basename(filename);
if (*dir == '.')
{ /* relative pathname */
e = this->db->query(this->db,
"SELECT fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"WHERE fh.product = ? AND f.name = ? AND fh.algo = ?",
DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB);
}
else
{ /* absolute pathname */
int did;
/* find directory entry first */
e = this->db->query(this->db,
"SELECT id FROM directories WHERE path = ?",
DB_TEXT, dir, DB_INT);
if (!e || !e->enumerate(e, &did))
{
goto err;
}
e->destroy(e);
e = this->db->query(this->db,
"SELECT fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"WHERE fh.product = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
DB_INT, pid, DB_INT, did, DB_TEXT, file, DB_INT, algo, DB_BLOB);
}
err:
free(file);
free(dir);
return e;
}
METHOD(pts_database_t, check_comp_measurement, status_t,
private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
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, aik_id, 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 = VERIFY_ERROR;
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 aik_id,
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, aik_id, 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 aik_id)
{
return this->db->execute(this->db, NULL,
"DELETE FROM component_hashes "
"WHERE component = ? AND key = ?",
DB_INT, cid, DB_INT, aik_id);
}
METHOD(pts_database_t, get_comp_measurement_count, status_t,
private_pts_database_t *this, pts_comp_func_name_t *comp_name,
int aik_id, pts_meas_algorithms_t algo, int *cid, int *count)
{
enumerator_t *e;
status_t status = SUCCESS;
/* Initialize count */
*count = 0;
/* 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, aik_id, 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)
{
free(this);
}
/**
* See header
*/
pts_database_t *pts_database_create(imv_database_t *imv_db)
{
private_pts_database_t *this;
if (!imv_db)
{
return NULL;
}
INIT(this,
.public = {
.get_pathname = _get_pathname,
.create_file_hash_enumerator = _create_file_hash_enumerator,
.add_file_measurement = _add_file_measurement,
.create_file_meas_enumerator = _create_file_meas_enumerator,
.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 = imv_db->get_database(imv_db),
);
return &this->public;
}
+155
View File
@@ -0,0 +1,155 @@
/*
* 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.
*/
/**
* @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 <imv/imv_database.h>
#include <library.h>
/**
* Class implementing the PTS File Measurement database
*
*/
struct pts_database_t {
/**
* Get absolute pathname for file or directory measurement
*
* @param is_dir TRUE if dir, FALSE if file
* @param id Primary key into directories or files table
* @return Absolute pathname as a text string
*/
char* (*get_pathname)(pts_database_t *this, bool is_dir, int id);
/**
* Get stored measurement hash for single file or directory entries
*
* @param pid Primary key of software product in database
* @param algo Hash algorithm used for measurement
* @param is_dir TRUE if directory was measured
* @param id Primary key of measured file/directory
* @return Enumerator over all matching measurement hashes
*/
enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
int pid, pts_meas_algorithms_t algo,
bool is_dir, int id);
/**
* Add PTS file measurement reference value
*
* @param pid Primary key of software product in database
* @param algo File measurement hash algorithm used
* @param measurement File measurement hash
* @param filename Optional name of the file to be checked
* @param is_dir TRUE if part of directory measurement
* @param id Primary key into direcories/files table
* @return Status
*/
status_t (*add_file_measurement)(pts_database_t *this, int pid,
pts_meas_algorithms_t algo,
chunk_t measurement, char *filename,
bool is_dir, int id);
/**
* Get PTS measurement[s] for a given filename stored in database
*
* @param pid Primary key of software product in database
* @param algo File measurement hash algorithm used
* @param filename Name of the file to be checked
* @return Enumerator over all matching measurement hashes
*/
enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, int pid,
pts_meas_algorithms_t algo,
char *filename);
/**
* Check a functional component measurement against value stored in database
*
* @param measurement measurement hash
* @param cid Primary key of Component Functional Name entry
* @param aik_id Primary key of AIK entry in database
* @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 aik_id, 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 aik_id Primary key of AIK entry in database
* @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 aik_id, 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 aik_id Primary key of AIK entry in database
* @return number of deleted measurement entries
*/
int (*delete_comp_measurements)(pts_database_t *this, int cid, int aik_id);
/**
* Get the number of measurements for a functional component and AIK
*
* @param comp_name Component Functional Name
* @param aik_id Primary key of AIK entry in database
* @param algo Hash algorithm used for measurement
* @param cid Primary key of Component Functional Name entry
* @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, int aik_id,
pts_meas_algorithms_t algo, int *cid, int *count);
/**
* Destroys a pts_database_t object.
*/
void (*destroy)(pts_database_t *this);
};
/**
* Creates an pts_database_t object
*
* @param imv_db Already attached IMV database
*/
pts_database_t* pts_database_create(imv_database_t *imv_db);
#endif /** PTS_DATABASE_H_ @}*/
+184
View File
@@ -0,0 +1,184 @@
/*
* 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 <utils/debug.h>
/**
* Described in header.
*/
bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_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)
{
/* mandatory PTS DH group is available */
return TRUE;
}
if (*dh_groups == PTS_DH_GROUP_NONE)
{
DBG1(DBG_PTS, "no PTS DH group available");
return FALSE;
}
if (mandatory_dh_groups)
{
DBG1(DBG_PTS, format2, "mandatory", diffie_hellman_group_names,
ECP_256_BIT);
return FALSE;
}
/* at least one optional PTS DH group is available */
return TRUE;
}
/**
* 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;
}
}
+107
View File
@@ -0,0 +1,107 @@
/*
* 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
* @param mandatory_dh_groups if TRUE enforce mandatory PTS DH groups
* @return TRUE if mandatory DH groups are available
* or at least one optional DH group if
* mandatory_dh_groups is set to FALSE.
*/
bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_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_groups,
pts_dh_group_t offered_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_ @}*/
+99
View File
@@ -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;
pen_type_t error_code = { PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED };
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(error_code, 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;
pen_type_t error_code = { PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED };
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(error_code, 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;
pen_type_t error_code = { PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH };
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(error_code, msg_info);
writer->destroy(writer);
return attr;
}
+89
View File
@@ -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_ @}*/
+414
View File
@@ -0,0 +1,414 @@
/*
* Copyright (C) 2011 Sansar Choinyambuu
* Copyright (C) 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 "pts_file_meas.h"
#include <collections/linked_list.h>
#include <utils/debug.h>
#include <sys/stat.h>
#include <libgen.h>
#include <errno.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, check, bool,
private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
pts_meas_algorithms_t algo)
{
enumerator_t *enumerator, *e;
entry_t *entry;
chunk_t hash;
int count_ok = 0, count_not_found = 0, count_differ = 0;
status_t status;
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
status = NOT_FOUND;
e = pts_db->create_file_meas_enumerator(pts_db, pid, algo,
entry->filename);
if (e)
{
while (e->enumerate(e, &hash))
{
if (chunk_equals(entry->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", &entry->measurement,
entry->filename);
count_ok++;
break;
case NOT_FOUND:
DBG2(DBG_PTS, " %#B for '%s' not found", &entry->measurement,
entry->filename);
count_not_found++;
break;
case VERIFY_ERROR:
DBG1(DBG_PTS, " %#B for '%s' differs", &entry->measurement,
entry->filename);
count_differ++;
break;
case FAILED:
default:
DBG1(DBG_PTS, " %#B for '%s' failed", &entry->measurement,
entry->filename);
}
}
enumerator->destroy(enumerator);
DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
this->list->get_count(this->list),
count_ok, count_not_found, count_differ);
return TRUE;
}
METHOD(pts_file_meas_t, verify, bool,
private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
{
int fid, fid_last = 0;
char *filename;
chunk_t measurement;
entry_t *entry;
enumerator_t *enumerator = NULL;
bool found = FALSE, match = FALSE, success = TRUE;
while (e_hash->enumerate(e_hash, &fid, &filename, &measurement))
{
if (fid != fid_last)
{
if (found && !match)
{
/* no matching hash value found for last filename */
success = FALSE;
DBG1(DBG_PTS, " %#B for '%s' is incorrect",
&entry->measurement, entry->filename);
enumerator->destroy(enumerator);
}
/* get a new filename from the database */
found = FALSE;
match = FALSE;
fid_last = fid;
/**
* check if we find an entry for this filename
* in the PTS measurement list
*/
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
if (!is_dir || streq(filename, entry->filename))
{
found = TRUE;
break;
}
}
/* no PTS measurement returned for this filename */
if (!found)
{
success = FALSE;
DBG1(DBG_PTS, " no measurement found for '%s'", filename);
enumerator->destroy(enumerator);
}
}
if (found && !match)
{
if (chunk_equals(measurement, entry->measurement))
{
match = TRUE;
DBG2(DBG_PTS, " %#B for '%s' is ok",
&entry->measurement, entry->filename);
enumerator->destroy(enumerator);
}
}
}
if (found && !match)
{
/* no matching hash value found for the very last filename */
success = FALSE;
DBG1(DBG_PTS, " %#B for '%s' is incorrect",
&entry->measurement, entry->filename);
enumerator->destroy(enumerator);
}
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,
.check = _check,
.verify = _verify,
.destroy = _destroy,
},
.request_id = request_id,
.list = linked_list_create(),
);
return &this->public;
}
/**
* Hash a file with a given absolute pathname
*/
static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
{
u_char buffer[4096];
size_t bytes_read;
bool success = TRUE;
FILE *file;
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)
{
if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
{
DBG1(DBG_PTS, " hasher increment error");
success = FALSE;
break;
}
}
else
{
if (!hasher->get_hash(hasher, chunk_empty, hash))
{
DBG1(DBG_PTS, " hasher finalize error");
success = FALSE;
}
break;
}
}
fclose(file);
return success;
}
/**
* See header
*/
pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
char *pathname, bool is_dir, bool use_rel_name,
pts_meas_algorithms_t alg)
{
private_pts_file_meas_t *this;
hash_algorithm_t hash_alg;
hasher_t *hasher;
u_char hash[HASH_SIZE_SHA384];
chunk_t measurement;
char* filename;
bool success = TRUE;
/* Create a hasher and a hash measurement buffer */
hash_alg = pts_meas_algo_to_hash(alg);
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;
}
measurement = chunk_create(hash, hasher->get_hash_size(hasher));
this = (private_pts_file_meas_t*)pts_file_meas_create(request_id);
if (is_dir)
{
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));
success = FALSE;
goto end;
}
while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
{
/* measure regular files only */
if (S_ISREG(st.st_mode) && *rel_name != '.')
{
if (!hash_file(hasher, abs_name, hash))
{
continue;
}
filename = use_rel_name ? rel_name : abs_name;
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
add(this, filename, measurement);
}
}
enumerator->destroy(enumerator);
}
else
{
if (!hash_file(hasher, pathname, hash))
{
success = FALSE;
goto end;
}
filename = use_rel_name ? path_basename(pathname) : strdup(pathname);
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
add(this, filename, measurement);
free(filename);
}
end:
hasher->destroy(hasher);
if (success)
{
return &this->public;
}
else
{
destroy(this);
return NULL;
}
}
+112
View File
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2011 Sansar Choinyambuu
* Copyright (C) 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.
*/
/**
* @defgroup pts_file_meas pts_file_meas
* @{ @ingroup pts
*/
#ifndef PTS_FILE_MEAS_H_
#define PTS_FILE_MEAS_H_
#include "pts/pts_database.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);
/**
* Check PTS File Measurements against reference value in the database
*
* @param db PTS Measurement database
* @param pid Primary key of software product in database
* @param algo PTS Measurement algorithm used
* @return TRUE if all measurements agreed
*/
bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid,
pts_meas_algorithms_t algo);
/**
* Verify stored hashes against PTS File Measurements
*
* @param e_hash Hash enumerator
* @param 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);
/**
* Creates a pts_file_meas_t object measuring a file/directory
*
* @param request_id ID of PTS File Measurement Request
* @param pathname Absolute file or directory pathname
* @param is_dir TRUE if directory path
* @param use_rel_name TRUE if relative filenames are to be used
* @param alg PTS hash measurement algorithm to be used
*/
pts_file_meas_t* pts_file_meas_create_from_path(u_int16_t request_id,
char* pathname, bool is_dir, bool use_rel_name,
pts_meas_algorithms_t alg);
#endif /** PTS_FILE_MEAS_H_ @}*/
+96
View File
@@ -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 <collections/linked_list.h>
#include <utils/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;
}
+85
View File
@@ -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_ @}*/
+33
View File
@@ -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"
);
+63
View File
@@ -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_ @}*/
+294
View File
@@ -0,0 +1,294 @@
/*
* 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 "pts_ima_bios_list.h"
#include <utils/debug.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
typedef struct private_pts_ima_bios_list_t private_pts_ima_bios_list_t;
typedef struct bios_entry_t bios_entry_t;
typedef enum event_type_t event_type_t;
enum event_type_t {
/* BIOS Events (TCG PC Client Specification for Conventional BIOS 1.21) */
EV_PREBOOT_CERT = 0x00000000,
EV_POST_CODE = 0x00000001,
EV_UNUSED = 0x00000002,
EV_NO_ACTION = 0x00000003,
EV_SEPARATOR = 0x00000004,
EV_ACTION = 0x00000005,
EV_EVENT_TAG = 0x00000006,
EV_S_CRTM_CONTENTS = 0x00000007,
EV_S_CRTM_VERSION = 0x00000008,
EV_CPU_MICROCODE = 0x00000009,
EV_PLATFORM_CONFIG_FLAGS = 0x0000000A,
EV_TABLE_OF_DEVICES = 0x0000000B,
EV_COMPACT_HASH = 0x0000000C,
EV_IPL = 0x0000000D,
EV_IPL_PARTITION_DATA = 0x0000000E,
EV_NONHOST_CODE = 0x0000000F,
EV_NONHOST_CONFIG = 0x00000010,
EV_NONHOST_INFO = 0x00000011,
EV_OMIT_BOOT_DEVICE_EVENTS = 0x00000012,
/* EFI Events (TCG EFI Platform Specification 1.22) */
EV_EFI_EVENT_BASE = 0x80000000,
EV_EFI_VARIABLE_DRIVER_CONFIG = 0x80000001,
EV_EFI_VARIABLE_BOOT = 0x80000002,
EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003,
EV_EFI_BOOT_SERVICES_DRIVER = 0x80000004,
EV_EFI_RUNTIME_SERVICES_DRIVER = 0x80000005,
EV_EFI_GPT_EVENT = 0x80000006,
EV_EFI_ACTION = 0x80000007,
EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x80000008,
EV_EFI_HANDOFF_TABLES = 0x80000009,
EV_EFI_VARIABLE_AUTHORITY = 0x800000E0
};
ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS,
"Preboot Cert",
"POST Code",
"Unused",
"No Action",
"Separator",
"Action",
"Event Tag",
"S-CRTM Contents",
"S-CRTM Version",
"CPU Microcode",
"Platform Config Flags",
"Table of Devices",
"Compact Hash",
"IPL",
"IPL Partition Data",
"Nonhost Code",
"Nonhost Config",
"Nonhost Info",
"Omit Boot Device Events"
);
ENUM_NEXT(event_type_names, EV_EFI_EVENT_BASE, EV_EFI_HANDOFF_TABLES,
EV_OMIT_BOOT_DEVICE_EVENTS,
"EFI Event Base",
"EFI Variable Driver Config",
"EFI Variable Boot",
"EFI Boot Services Application",
"EFI Boot Services Driver",
"EFI Runtime Services Driver",
"EFI GPT Event",
"EFI Action",
"EFI Platform Firmware Blob",
"EFI Handoff Tables"
);
ENUM_NEXT(event_type_names, EV_EFI_VARIABLE_AUTHORITY, EV_EFI_VARIABLE_AUTHORITY,
EV_EFI_HANDOFF_TABLES,
"EFI Variable Authority"
);
ENUM_END(event_type_names, EV_EFI_VARIABLE_AUTHORITY);
/**
* Private data of a pts_ima_bios_list_t object.
*
*/
struct private_pts_ima_bios_list_t {
/**
* Public pts_ima_bios_list_t interface.
*/
pts_ima_bios_list_t public;
/**
* List of BIOS measurement entries
*/
linked_list_t *list;
/**
* Time when BIOS measurements were taken
*/
time_t creation_time;
};
/**
* Linux IMA BIOS measurement entry
*/
struct bios_entry_t {
/**
* PCR register
*/
uint32_t pcr;
/**
* SHA1 measurement hash
*/
chunk_t measurement;
};
/**
* Free a bios_entry_t object
*/
static void free_bios_entry(bios_entry_t *this)
{
free(this->measurement.ptr);
free(this);
}
METHOD(pts_ima_bios_list_t, get_time, time_t,
private_pts_ima_bios_list_t *this)
{
return this->creation_time;
}
METHOD(pts_ima_bios_list_t, get_count, int,
private_pts_ima_bios_list_t *this)
{
return this->list->get_count(this->list);
}
METHOD(pts_ima_bios_list_t, get_next, status_t,
private_pts_ima_bios_list_t *this, uint32_t *pcr, chunk_t *measurement)
{
bios_entry_t *entry;
status_t status;
status = this->list->remove_first(this->list, (void**)&entry);
*pcr = entry->pcr;
*measurement = entry->measurement;
free(entry);
return status;
}
METHOD(pts_ima_bios_list_t, destroy, void,
private_pts_ima_bios_list_t *this)
{
this->list->destroy_function(this->list, (void *)free_bios_entry);
free(this);
}
/**
* See header
*/
pts_ima_bios_list_t* pts_ima_bios_list_create(char *file)
{
private_pts_ima_bios_list_t *this;
uint32_t pcr, event_type, event_len, seek_len;
uint32_t buf_len = 2048;
uint8_t event_buf[buf_len];
chunk_t event;
bios_entry_t *entry;
struct stat st;
ssize_t res;
int fd;
fd = open(file, O_RDONLY);
if (fd == -1)
{
DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
return NULL;
}
if (fstat(fd, &st) == -1)
{
DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
strerror(errno));
close(fd);
return FALSE;
}
INIT(this,
.public = {
.get_time = _get_time,
.get_count = _get_count,
.get_next = _get_next,
.destroy = _destroy,
},
.creation_time = st.st_ctime,
.list = linked_list_create(),
);
DBG2(DBG_PTS, "PCR Event Type (Size)");
while (TRUE)
{
res = read(fd, &pcr, 4);
if (res == 0)
{
DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
file, this->list->get_count(this->list));
close(fd);
return &this->public;
}
entry = malloc_thing(bios_entry_t);
entry->pcr = pcr;
entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
if (res != 4)
{
break;
}
if (read(fd, &event_type, 4) != 4)
{
break;
}
if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
{
break;
}
if (read(fd, &event_len, 4) != 4)
{
break;
}
DBG2(DBG_PTS, "%2u %N (%u bytes)", pcr, event_type_names, event_type,
event_len);
seek_len = (event_len > buf_len) ? event_len - buf_len : 0;
event_len -= seek_len;
if (read(fd, event_buf, event_len) != event_len)
{
break;
}
event = chunk_create(event_buf, event_len);
DBG3(DBG_PTS,"%B", &event);
if (event_type == EV_ACTION || event_type == EV_EFI_ACTION)
{
DBG2(DBG_PTS, " '%.*s'", event_len, event_buf);
}
if (seek_len > 0 && lseek(fd, seek_len, SEEK_CUR) == -1)
{
break;
}
this->list->insert_last(this->list, entry);
}
DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
strerror(errno));
free_bios_entry(entry);
close(fd);
destroy(this);
return NULL;
}
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (C) 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.
*/
/**
* @defgroup pts_ima_bios_list pts_ima_bios_list
* @{ @ingroup pts
*/
#ifndef PTS_IMA_BIOS_LIST_H_
#define PTS_IMA_BIOS_LIST_H_
#include <time.h>
#include <library.h>
typedef struct pts_ima_bios_list_t pts_ima_bios_list_t;
/**
* Class retrieving Linux IMA BIOS measurements
*
*/
struct pts_ima_bios_list_t {
/**
* Get the time the BIOS measurements were taken
*
* @return Measurement time
*/
time_t (*get_time)(pts_ima_bios_list_t *this);
/**
* Get the number of non-processed BIOS measurements
*
* @return Number of measurements left
*/
int (*get_count)(pts_ima_bios_list_t *this);
/**
* Get the next BIOS measurement and remove it from the list
*
* @param pcr PCR where the measurement was extended into
* @param measurement Measurement hash
* @return Return code
*/
status_t (*get_next)(pts_ima_bios_list_t *this, uint32_t *pcr,
chunk_t *measurement);
/**
* Destroys a pts_ima_bios_list_t object.
*/
void (*destroy)(pts_ima_bios_list_t *this);
};
/**
* Create a PTS IMA BIOS measurement object
*
* @param file Pathname pointing to the BIOS measurements
*/
pts_ima_bios_list_t* pts_ima_bios_list_create(char *file);
#endif /** PTS_IMA_BIOS_LIST_H_ @}*/
+330
View File
@@ -0,0 +1,330 @@
/*
* 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 "pts_ima_event_list.h"
#include <utils/debug.h>
#include <crypto/hashers/hasher.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
typedef struct private_pts_ima_event_list_t private_pts_ima_event_list_t;
typedef struct event_entry_t event_entry_t;
#define IMA_TYPE_LEN 3
#define IMA_NG_TYPE_LEN 6
#define IMA_TYPE_LEN_MAX 10
#define IMA_ALGO_DIGEST_LEN_MAX IMA_ALGO_LEN_MAX + HASH_SIZE_SHA512
/**
* Private data of a pts_ima_event_list_t object.
*
*/
struct private_pts_ima_event_list_t {
/**
* Public pts_ima_event_list_t interface.
*/
pts_ima_event_list_t public;
/**
* List of BIOS measurement entries
*/
linked_list_t *list;
/**
* Time when IMA runtime file measurements were taken
*/
time_t creation_time;
};
/**
* Linux IMA runtime file measurement entry
*/
struct event_entry_t {
/**
* SHA1 measurement hash
*/
chunk_t measurement;
/**
* IMA-NG hash algorithm name or NULL
*/
char *algo;
/**
* IMA-NG eventname or IMA filename
*/
char *name;
};
/**
* Free an ima_event_t object
*/
static void free_event_entry(event_entry_t *this)
{
free(this->measurement.ptr);
free(this->algo);
free(this->name);
free(this);
}
METHOD(pts_ima_event_list_t, get_time, time_t,
private_pts_ima_event_list_t *this)
{
return this->creation_time;
}
METHOD(pts_ima_event_list_t, get_count, int,
private_pts_ima_event_list_t *this)
{
return this->list->get_count(this->list);
}
METHOD(pts_ima_event_list_t, get_next, status_t,
private_pts_ima_event_list_t *this, chunk_t *measurement, char **algo,
char **name)
{
event_entry_t *entry;
status_t status;
status = this->list->remove_first(this->list, (void**)&entry);
*measurement = entry->measurement;
*algo = entry->algo;
*name = entry->name;
free(entry);
return status;
}
METHOD(pts_ima_event_list_t, destroy, void,
private_pts_ima_event_list_t *this)
{
this->list->destroy_function(this->list, (void *)free_event_entry);
free(this);
}
/**
* See header
*/
pts_ima_event_list_t* pts_ima_event_list_create(char *file)
{
private_pts_ima_event_list_t *this;
event_entry_t *entry;
uint32_t pcr, type_len, name_len, eventdata_len, algo_digest_len, algo_len;
char type[IMA_TYPE_LEN_MAX];
char algo_digest[IMA_ALGO_DIGEST_LEN_MAX];
char *pos, *error = "";
struct stat st;
ssize_t res;
bool ima_ng;
int fd;
fd = open(file, O_RDONLY);
if (fd == -1)
{
DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
return NULL;
}
if (fstat(fd, &st) == -1)
{
DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
strerror(errno));
close(fd);
return NULL;
}
INIT(this,
.public = {
.get_time = _get_time,
.get_count = _get_count,
.get_next = _get_next,
.destroy = _destroy,
},
.creation_time = st.st_ctime,
.list = linked_list_create(),
);
while (TRUE)
{
/* read 32 bit PCR number in host order */
res = read(fd, &pcr, 4);
/* exit if no more measurement data is available */
if (res == 0)
{
DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
file, this->list->get_count(this->list));
close(fd);
return &this->public;
}
/* create and initialize new IMA entry */
entry = malloc_thing(event_entry_t);
entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
entry->algo = NULL;
entry->name = NULL;
if (res != 4 || pcr != IMA_PCR)
{
error = "invalid IMA PCR field";
break;
}
/* read 20 byte SHA-1 measurement digest */
if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
{
error = "invalid SHA-1 digest field";
break;
}
/* read 32 bit length of IMA type string in host order */
if (read(fd, &type_len, 4) != 4 || type_len > IMA_TYPE_LEN_MAX)
{
error = "invalid IMA type field length";
break;
}
/* read and interpret IMA type string */
if (read(fd, type, type_len) != type_len)
{
error = "invalid IMA type field";
break;
}
if (type_len == IMA_NG_TYPE_LEN &&
memeq(type, "ima-ng", IMA_NG_TYPE_LEN))
{
ima_ng = TRUE;
}
else if (type_len == IMA_TYPE_LEN &&
memeq(type, "ima", IMA_TYPE_LEN))
{
ima_ng = FALSE;
}
else
{
error = "unknown IMA type";
break;
}
if (ima_ng)
{
/* read the 32 bit length of the event data in host order */
if (read(fd, &eventdata_len, 4) != 4 || eventdata_len < 4)
{
error = "invalid event data field length";
break;
}
/* read the 32 bit length of the algo_digest string in host order */
if (read(fd, &algo_digest_len, 4) != 4 ||
algo_digest_len > IMA_ALGO_DIGEST_LEN_MAX ||
eventdata_len < 4 + algo_digest_len + 4)
{
error = "invalid digest_with_algo field length";
break;
}
/* read the IMA algo_digest string */
if (read(fd, algo_digest, algo_digest_len) != algo_digest_len)
{
error = "invalid digest_with_algo field";
break;
}
/* extract the hash algorithm name */
pos = memchr(algo_digest, '\0', algo_digest_len);
if (!pos)
{
error = "no algo field";
break;
}
algo_len = pos - algo_digest + 1;
if (algo_len > IMA_ALGO_LEN_MAX ||
algo_len < IMA_ALGO_LEN_MIN || *(pos - 1) != ':')
{
error = "invalid algo field";
break;
}
/* copy and store the hash algorithm name */
entry->algo = malloc(algo_len);
memcpy(entry->algo, algo_digest, algo_len);
/* read the 32 bit length of the event name in host order */
if (read(fd, &name_len, 4) != 4 ||
eventdata_len != 4 + algo_digest_len + 4 + name_len)
{
error = "invalid filename field length";
break;
}
/* allocate memory for the file name */
entry->name = malloc(name_len);
/* read file name */
if (read(fd, entry->name, name_len) != name_len)
{
error = "invalid filename field";
break;
}
}
else
{
/* skip SHA-1 digest of the file content */
if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
{
break;
}
/* read the 32 bit length of the file name in host order */
if (read(fd, &name_len, 4) != 4 || name_len == UINT32_MAX)
{
error = "invalid filename field length";
break;
}
/* allocate memory for the file name */
entry->name = malloc(name_len + 1);
/* read file name */
if (read(fd, entry->name, name_len) != name_len)
{
error = "invalid eventname field";
break;
}
/* terminate the file name with a nul character */
entry->name[name_len] = '\0';
}
this->list->insert_last(this->list, entry);
}
DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s", file, error);
free_event_entry(entry);
close(fd);
destroy(this);
return NULL;
}
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (C) 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.
*/
/**
* @defgroup pts_ima_event_list pts_ima_event_list
* @{ @ingroup pts
*/
#ifndef PTS_IMA_EVENT_LIST_H_
#define PTS_IMA_EVENT_LIST_H_
#include <time.h>
#include <library.h>
typedef struct pts_ima_event_list_t pts_ima_event_list_t;
#define IMA_PCR 10
#define IMA_ALGO_LEN_MIN 5
#define IMA_ALGO_LEN_MAX 8
/**
* Class retrieving Linux IMA file measurements
*
*/
struct pts_ima_event_list_t {
/**
* Get the time the file measurements were taken
*
* @return Measurement time
*/
time_t (*get_time)(pts_ima_event_list_t *this);
/**
* Get the number of non-processed file measurements
*
* @return Number of measurements left
*/
int (*get_count)(pts_ima_event_list_t *this);
/**
* Get the next file measurement and remove it from the list
*
* @param measurement Measurement hash
* @param algo Algorithm used to hash files
" @param name Event name (absolute filename or boot_aggregate)
* @return Return code
*/
status_t (*get_next)(pts_ima_event_list_t *this, chunk_t *measurement,
char **algo, char **name);
/**
* Destroys a pts_ima_event_list_t object.
*/
void (*destroy)(pts_ima_event_list_t *this);
};
/**
* Create a PTS IMA runtime file measurement object
*
* @param file Pathname pointing to the IMA runtme measurements
*/
pts_ima_event_list_t* pts_ima_event_list_create(char *file);
#endif /** PTS_IMA_EVENT_LIST_H_ @}*/
+176
View File
@@ -0,0 +1,176 @@
/*
* 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 "pts_meas_algo.h"
#include <utils/debug.h>
ENUM_BEGIN(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_NONE,
"None");
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
PTS_MEAS_ALGO_NONE,
"SHA384");
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
PTS_MEAS_ALGO_SHA384,
"SHA256");
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
PTS_MEAS_ALGO_SHA256,
"SHA1");
ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1);
/**
* 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;
}
}
+106
View File
@@ -0,0 +1,106 @@
/*
* Copyright (C) 2011 Sansar Choinyambuu
* 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.
*/
/**
* @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_SHA384 = (1<<13),
PTS_MEAS_ALGO_SHA256 = (1<<14),
PTS_MEAS_ALGO_SHA1 = (1<<15)
};
/**
* 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_ @}*/
+289
View File
@@ -0,0 +1,289 @@
/*
* Copyright (C) 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 "pts_pcr.h"
#include <utils/debug.h>
#include <stdarg.h>
typedef struct private_pts_pcr_t private_pts_pcr_t;
/**
* Private data of a pts_pcr_t object.
*
*/
struct private_pts_pcr_t {
/**
* Public pts_pcr_t interface.
*/
pts_pcr_t public;
/**
* Shadow PCR registers
*/
chunk_t pcrs[PTS_PCR_MAX_NUM];
/**
* 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[PTS_PCR_MAX_NUM / 8];
/**
* Hasher used to extend shadow PCRs
*/
hasher_t *hasher;
};
METHOD(pts_pcr_t, get_count, u_int32_t,
private_pts_pcr_t *this)
{
return this->pcr_count;
}
METHOD(pts_pcr_t, select_pcr, bool,
private_pts_pcr_t *this, u_int32_t pcr)
{
u_int32_t i, f;
if (pcr >= PTS_PCR_MAX_NUM)
{
DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
pcr, PTS_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_pcr_t, get_selection_size, size_t,
private_pts_pcr_t *this)
{
/**
* A TPM v1.2 has 24 PCR Registers so the bitmask field length
* used by TrouSerS is at least 3 bytes
*/
return PTS_PCR_MAX_NUM / 8;
}
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** current PCR */
u_int32_t pcr;
/** back reference to parent */
private_pts_pcr_t *pcrs;
} pcr_enumerator_t;
/**
* Implementation of enumerator.enumerate
*/
static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
{
u_int32_t *pcr, i, f;
va_list args;
va_start(args, this);
pcr = va_arg(args, u_int32_t*);
va_end(args);
while (this->pcr <= this->pcrs->pcr_max)
{
/* Determine PCR selection flag */
i = this->pcr / 8;
f = 1 << (this->pcr - 8*i);
/* Assign current PCR to output argument and increase */
*pcr = this->pcr++;
/* return if PCR is selected */
if (this->pcrs->pcr_select[i] & f)
{
return TRUE;
}
}
return FALSE;
}
METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
private_pts_pcr_t *this)
{
pcr_enumerator_t *enumerator;
INIT(enumerator,
.public = {
.enumerate = (void*)pcr_enumerator_enumerate,
.destroy = (void*)free,
},
.pcrs = this,
);
return (enumerator_t*)enumerator;
}
METHOD(pts_pcr_t, get, chunk_t,
private_pts_pcr_t *this, u_int32_t pcr)
{
return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
}
METHOD(pts_pcr_t, set, bool,
private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
{
if (value.len != PTS_PCR_LEN)
{
DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
return FALSE;
}
if (select_pcr(this, pcr))
{
memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
return TRUE;
}
return FALSE;
}
METHOD(pts_pcr_t, extend, chunk_t,
private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
{
if (measurement.len != PTS_PCR_LEN)
{
DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
return chunk_empty;
}
if (!select_pcr(this, pcr))
{
return chunk_empty;
}
if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
!this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
{
DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
return chunk_empty;
}
return this->pcrs[pcr];
}
METHOD(pts_pcr_t, get_composite, chunk_t,
private_pts_pcr_t *this)
{
chunk_t composite;
enumerator_t *enumerator;
u_int16_t selection_size;
u_int32_t pcr_field_size, pcr;
u_char *pos;
selection_size = get_selection_size(this);
pcr_field_size = this->pcr_count * PTS_PCR_LEN;
composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
pos = composite.ptr;
htoun16(pos, selection_size);
pos += 2;
memcpy(pos, this->pcr_select, selection_size);
pos += selection_size;
htoun32(pos, pcr_field_size);
pos += 4;
enumerator = create_enumerator(this);
while (enumerator->enumerate(enumerator, &pcr))
{
memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
pos += PTS_PCR_LEN;
}
enumerator->destroy(enumerator);
DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
return composite;
}
METHOD(pts_pcr_t, destroy, void,
private_pts_pcr_t *this)
{
u_int32_t i;
for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{
free(this->pcrs[i].ptr);
}
this->hasher->destroy(this->hasher);
free(this);
}
/**
* See header
*/
pts_pcr_t *pts_pcr_create(void)
{
private_pts_pcr_t *this;
hasher_t *hasher;
u_int32_t i;
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 NULL;
}
INIT(this,
.public = {
.get_count = _get_count,
.select_pcr = _select_pcr,
.get_selection_size = _get_selection_size,
.create_enumerator = _create_enumerator,
.get = _get,
.set = _set,
.extend = _extend,
.get_composite = _get_composite,
.destroy = _destroy,
},
.hasher = hasher,
);
for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{
this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
}
return &this->public;
}
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright (C) 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_pcr pts_pcr
* @{ @ingroup pts
*/
#ifndef PTS_PCR_H_
#define PTS_PCR_H_
typedef struct pts_pcr_t pts_pcr_t;
#include <library.h>
/**
* Maximum number of PCR's of TPM, TPM Spec 1.2
*/
#define PTS_PCR_MAX_NUM 24
/**
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
*/
#define PTS_PCR_LEN 20
/**
* Class implementing a shadow PCR register set
*/
struct pts_pcr_t {
/**
* Get the number of selected PCRs
*
* @return number of selected PCRs
*/
u_int32_t (*get_count)(pts_pcr_t *this);
/**
* Mark a PCR as selected
*
* @param pcr index of PCR
* @return TRUE if PCR index exists
*/
bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
/**
* Get the size of the selection field in bytes
*
* @return number of bytes written
*/
size_t (*get_selection_size)(pts_pcr_t *this);
/**
* Create an enumerator over all selected PCR indexes
*
* @return enumerator
*/
enumerator_t* (*create_enumerator)(pts_pcr_t *this);
/**
* Get the current content of a PCR
*
* @param pcr index of PCR
* @return content of PCR
*/
chunk_t (*get)(pts_pcr_t *this, u_int32_t pcr);
/**
* Set the content of a PCR
*
* @param pcr index of PCR
* @param value new value of PCR
* @return TRUE if value could be set
*/
bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
/**
* Extend the content of a PCR
*
* @param pcr index of PCR
* @param measurement measurment value to be extended into PCR
* @return new content of PCR
*/
chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
/**
* Create a PCR Composite object over all selected PCRs
*
* @return PCR Composite object (must be freed)
*/
chunk_t (*get_composite)(pts_pcr_t *this);
/**
* Destroys a pts_pcr_t object.
*/
void (*destroy)(pts_pcr_t *this);
};
/**
* Creates an pts_pcr_t object
*/
pts_pcr_t* pts_pcr_create(void);
#endif /** PTS_PCR_H_ @}*/
+44
View File
@@ -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_ @}*/
+42
View File
@@ -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_ @}*/
+47
View File
@@ -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_ @}*/