Merged libpts into libimcv
This commit is contained in:
@@ -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_ @}*/
|
||||
@@ -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
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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"
|
||||
);
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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_ @}*/
|
||||
@@ -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_ @}*/
|
||||
@@ -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_ @}*/
|
||||
Reference in New Issue
Block a user