ipsec attest now can measure all files in a directory

This commit is contained in:
Andreas Steffen
2012-07-16 09:54:11 +02:00
parent 12ef9fb1b5
commit 0f236aacb5
9 changed files with 323 additions and 171 deletions
+4 -129
View File
@@ -23,12 +23,13 @@
#include <trousers/tss.h>
#include <trousers/trousers.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <libgen.h>
#include <unistd.h>
#include <errno.h>
#define PTS_BUF_SIZE 4096
/**
* Maximum number of PCR's of TPM, TPM Spec 1.2
*/
@@ -486,54 +487,6 @@ METHOD(pts_t, get_aik_keyid, bool,
return success;
}
METHOD(pts_t, hash_file, bool,
private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
{
u_char buffer[PTS_BUF_SIZE];
FILE *file;
int bytes_read;
file = fopen(pathname, "rb");
if (!file)
{
DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
strerror(errno));
return FALSE;
}
while (TRUE)
{
bytes_read = fread(buffer, 1, sizeof(buffer), file);
if (bytes_read > 0)
{
hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
}
else
{
hasher->get_hash(hasher, chunk_empty, hash);
break;
}
}
fclose(file);
return TRUE;
}
/**
* Get the relative filename of a fully qualified file pathname
*/
static char* get_filename(char *pathname)
{
char *pos, *filename;
pos = filename = pathname;
while (pos && *(++pos) != '\0')
{
filename = pos;
pos = strchr(filename, '/');
}
return filename;
}
METHOD(pts_t, is_path_valid, bool,
private_pts_t *this, char *path, pts_error_code_t *error_code)
{
@@ -565,82 +518,6 @@ METHOD(pts_t, is_path_valid, bool,
return TRUE;
}
METHOD(pts_t, do_measurements, pts_file_meas_t*,
private_pts_t *this, u_int16_t request_id, char *pathname, bool is_directory)
{
hasher_t *hasher;
hash_algorithm_t hash_alg;
u_char hash[HASH_SIZE_SHA384];
chunk_t measurement;
pts_file_meas_t *measurements;
/* Create a hasher */
hash_alg = pts_meas_algo_to_hash(this->algorithm);
hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
if (!hasher)
{
DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
return NULL;
}
/* Create a measurement object */
measurements = pts_file_meas_create(request_id);
/* Link the hash to the measurement and set the measurement length */
measurement = chunk_create(hash, hasher->get_hash_size(hasher));
if (is_directory)
{
enumerator_t *enumerator;
char *rel_name, *abs_name;
struct stat st;
enumerator = enumerator_create_directory(pathname);
if (!enumerator)
{
DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
strerror(errno));
hasher->destroy(hasher);
measurements->destroy(measurements);
return NULL;
}
while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
{
/* measure regular files only */
if (S_ISREG(st.st_mode) && *rel_name != '.')
{
if (!hash_file(this, hasher, abs_name, hash))
{
enumerator->destroy(enumerator);
hasher->destroy(hasher);
measurements->destroy(measurements);
return NULL;
}
DBG2(DBG_PTS, " %#B for '%s'", &measurement, rel_name);
measurements->add(measurements, rel_name, measurement);
}
}
enumerator->destroy(enumerator);
}
else
{
char *filename;
if (!hash_file(this, hasher, pathname, hash))
{
hasher->destroy(hasher);
measurements->destroy(measurements);
return NULL;
}
filename = get_filename(pathname);
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
measurements->add(measurements, filename, measurement);
}
hasher->destroy(hasher);
return measurements;
}
/**
* Obtain statistical information describing a file
*/
@@ -748,7 +625,7 @@ METHOD(pts_t, get_metadata, pts_file_meta_t*,
metadata->destroy(metadata);
return NULL;
}
entry->filename = strdup(get_filename(pathname));
entry->filename = strdup(basename(pathname));
metadata->add(metadata, entry);
}
@@ -1499,8 +1376,6 @@ pts_t *pts_create(bool is_imc)
.set_aik = _set_aik,
.get_aik_keyid = _get_aik_keyid,
.is_path_valid = _is_path_valid,
.hash_file = _hash_file,
.do_measurements = _do_measurements,
.get_metadata = _get_metadata,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
+2 -23
View File
@@ -229,35 +229,14 @@ struct pts_t {
*/
bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
/**
* Compute a hash over a file
* @param hasher Hasher to be used
* @param pathname Absolute path of a file
* @param hash Buffer to keep hash output
* @return TRUE if path is valid and hashing succeeded
*/
bool (*hash_file)(pts_t *this, hasher_t *hasher, char *pathname, u_char *hash);
/**
* Do PTS File Measurements
*
* @param request_id ID of PTS File Measurement Request
* @param pathname Absolute pathname of file to be measured
* @param is_directory TRUE if directory contents are measured
* @return PTS File Measurements of NULL if FAILED
*/
pts_file_meas_t* (*do_measurements)(pts_t *this, u_int16_t request_id,
char *pathname, bool is_directory);
/**
* Obtain file metadata
*
* @param pathname Absolute pathname of file/directory
* @param is_directory TRUE if directory contents are requested
* @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_directory);
pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
/**
* Reads given PCR value and returns it
+132
View File
@@ -18,6 +18,10 @@
#include <utils/linked_list.h>
#include <debug.h>
#include <sys/stat.h>
#include <libgen.h>
#include <errno.h>
typedef struct private_pts_file_meas_t private_pts_file_meas_t;
/**
@@ -201,3 +205,131 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
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;
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)
{
hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
}
else
{
hasher->get_hash(hasher, chunk_empty, hash);
break;
}
}
fclose(file);
return TRUE;
}
/**
* 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));
INIT(this,
.public = {
.get_request_id = _get_request_id,
.get_file_count = _get_file_count,
.add = _add,
.create_enumerator = _create_enumerator,
.insert = _insert,
.verify = _verify,
.destroy = _destroy,
},
.request_id = request_id,
.list = linked_list_create(),
);
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))
{
success = FALSE;
break;
}
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 ? basename(pathname) : pathname;
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
add(this, filename, measurement);
}
end:
hasher->destroy(hasher);
if (success)
{
return &this->public;
}
else
{
destroy(this);
return NULL;
}
}
+13
View File
@@ -93,4 +93,17 @@ struct pts_file_meas_t {
*/
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_ @}*/