diff options
Diffstat (limited to 'src/libpts/pts')
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_ima.c | 694 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_tboot.c | 95 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_tgrub.c | 7 | ||||
-rw-r--r-- | src/libpts/pts/components/pts_component.h | 5 | ||||
-rw-r--r-- | src/libpts/pts/pts.c | 152 | ||||
-rw-r--r-- | src/libpts/pts/pts.h | 22 | ||||
-rw-r--r-- | src/libpts/pts/pts_database.c | 172 | ||||
-rw-r--r-- | src/libpts/pts/pts_database.h | 62 | ||||
-rw-r--r-- | src/libpts/pts/pts_file_meas.c | 117 | ||||
-rw-r--r-- | src/libpts/pts/pts_file_meas.h | 5 | ||||
-rw-r--r-- | src/libpts/pts/pts_ima_bios_list.c | 294 | ||||
-rw-r--r-- | src/libpts/pts/pts_ima_bios_list.h | 74 | ||||
-rw-r--r-- | src/libpts/pts/pts_ima_event_list.c | 330 | ||||
-rw-r--r-- | src/libpts/pts/pts_ima_event_list.h | 80 | ||||
-rw-r--r-- | src/libpts/pts/pts_meas_algo.c | 7 | ||||
-rw-r--r-- | src/libpts/pts/pts_meas_algo.h | 4 |
16 files changed, 1379 insertions, 741 deletions
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c index c6b4131bf..be8aa40ad 100644 --- a/src/libpts/pts/components/ita/ita_comp_ima.c +++ b/src/libpts/pts/components/ita/ita_comp_ima.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,27 +18,20 @@ #include "libpts.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> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.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_PCR 10 -#define IMA_TYPE_LEN 3 -#define IMA_FILENAME_LEN_MAX 255 +#define IMA_FILENAME_LEN_MAX 255 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t; -typedef struct bios_entry_t bios_entry_t; -typedef struct ima_entry_t ima_entry_t; typedef enum ima_state_t ima_state_t; enum ima_state_t { @@ -66,14 +59,9 @@ struct pts_ita_comp_ima_t { pts_comp_func_name_t *name; /** - * AIK keyid - */ - chunk_t keyid; - - /** * Sub-component depth */ - u_int32_t depth; + uint32_t depth; /** * PTS measurement database @@ -83,7 +71,7 @@ struct pts_ita_comp_ima_t { /** * Primary key for AIK database entry */ - int kid; + int aik_id; /** * Primary key for IMA BIOS Component Functional Name database entry @@ -118,12 +106,12 @@ struct pts_ita_comp_ima_t { /** * IMA BIOS measurements */ - linked_list_t *bios_list; + pts_ima_bios_list_t *bios_list; /** * IMA runtime file measurements */ - linked_list_t *ima_list; + pts_ima_event_list_t *ima_list; /** * Whether to send pcr_before and pcr_after info @@ -131,9 +119,9 @@ struct pts_ita_comp_ima_t { bool pcr_info; /** - * IMA measurement time + * Creation time of measurement */ - time_t measurement_time; + time_t creation_time; /** * IMA state machine @@ -173,222 +161,11 @@ struct pts_ita_comp_ima_t { }; /** - * Linux IMA BIOS measurement entry - */ -struct bios_entry_t { - - /** - * PCR register - */ - u_int32_t pcr; - - /** - * SHA1 measurement hash - */ - chunk_t measurement; -}; - -/** - * Linux IMA runtime file measurement entry - */ -struct ima_entry_t { - - /** - * SHA1 measurement hash - */ - chunk_t measurement; - - /** - * absolute path of executable files or basename of dynamic libraries - */ - char *filename; -}; - -/** - * Free a bios_entry_t object - */ -static void free_bios_entry(bios_entry_t *this) -{ - free(this->measurement.ptr); - free(this); -} - -/** - * Free an ima_entry_t object - */ -static void free_ima_entry(ima_entry_t *this) -{ - free(this->measurement.ptr); - free(this->filename); - free(this); -} - -/** - * Load a PCR measurement file and determine the creation date - */ -static bool load_bios_measurements(char *file, linked_list_t *list, - time_t *created) -{ - u_int32_t pcr, num, len; - 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 FALSE; - } - - if (fstat(fd, &st) == -1) - { - DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file, - strerror(errno)); - close(fd); - return FALSE; - } - *created = st.st_ctime; - - while (TRUE) - { - res = read(fd, &pcr, 4); - if (res == 0) - { - DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)", - file, list->get_count(list)); - close(fd); - return TRUE; - } - - entry = malloc_thing(bios_entry_t); - entry->pcr = pcr; - entry->measurement = chunk_alloc(HASH_SIZE_SHA1); - - if (res != 4) - { - break; - } - if (read(fd, &num, 4) != 4) - { - break; - } - if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1) - { - break; - } - if (read(fd, &len, 4) != 4) - { - break; - } - if (lseek(fd, len, SEEK_CUR) == -1) - { - break; - } - list->insert_last(list, entry); - } - - DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file, - strerror(errno)); - free_bios_entry(entry); - close(fd); - return FALSE; -} - -/** - * Load an IMA runtime measurement file and determine the creation and - * update dates - */ -static bool load_runtime_measurements(char *file, linked_list_t *list, - time_t *created) -{ - u_int32_t pcr, len; - ima_entry_t *entry; - char type[IMA_TYPE_LEN]; - 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 TRUE; - } - - if (fstat(fd, &st) == -1) - { - DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file, - strerror(errno)); - close(fd); - return FALSE; - } - *created = st.st_ctime; - - while (TRUE) - { - res = read(fd, &pcr, 4); - if (res == 0) - { - DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)", - file, list->get_count(list)); - close(fd); - return TRUE; - } - - entry = malloc_thing(ima_entry_t); - entry->measurement = chunk_alloc(HASH_SIZE_SHA1); - entry->filename = NULL; - - if (res != 4 || pcr != IMA_PCR) - { - break; - } - if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1) - { - break; - } - if (read(fd, &len, 4) != 4 || len != IMA_TYPE_LEN) - { - break; - } - if (read(fd, type, IMA_TYPE_LEN) != IMA_TYPE_LEN || - memcmp(type, "ima", IMA_TYPE_LEN)) - { - break; - } - if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1) - { - break; - } - if (read(fd, &len, 4) != 4) - { - break; - } - entry->filename = malloc(len + 1); - if (read(fd, entry->filename, len) != len) - { - break; - } - entry->filename[len] = '\0'; - - list->insert_last(list, entry); - } - - DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s", - file, strerror(errno)); - free_ima_entry(entry); - close(fd); - return FALSE; -} - -/** - * Extend measurement into PCR an create evidence + * Extend measurement into PCR and create evidence */ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, - u_int8_t qualifier, pts_pcr_t *pcrs, - u_int32_t pcr, chunk_t measurement) + uint8_t qualifier, pts_pcr_t *pcrs, + uint32_t pcr, chunk_t measurement) { size_t pcr_len; pts_pcr_transform_t pcr_transform; @@ -414,7 +191,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, 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->measurement_time, measurement); + pcr_transform, this->creation_time, measurement); if (this->pcr_info) { pcr_after =chunk_clone(pcrs->get(pcrs, pcr)); @@ -424,15 +201,83 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, } /** + * 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) +static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement, + char *algo) { - u_int32_t i; - u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1]; u_char pcr_buffer[HASH_SIZE_SHA1]; - chunk_t file_name, boot_aggregate; + chunk_t boot_aggregate; hasher_t *hasher; + uint32_t i; bool success, pcr_ok = TRUE; hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); @@ -448,19 +293,20 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement) } if (pcr_ok) { - boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer)); - memset(filename_buffer, 0, sizeof(filename_buffer)); - strcpy(filename_buffer, "boot_aggregate"); - file_name = chunk_create (filename_buffer, sizeof(filename_buffer)); - - pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer) && - hasher->get_hash(hasher, boot_aggregate, NULL) && - hasher->get_hash(hasher, file_name, boot_aggregate.ptr); + 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"); @@ -479,26 +325,28 @@ METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*, return this->name; } -METHOD(pts_component_t, get_evidence_flags, u_int8_t, +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, u_int32_t, +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, u_int8_t qualifier, pts_t *pts, + pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts, pts_comp_evidence_t **evidence) { - bios_entry_t *bios_entry; - ima_entry_t *ima_entry; 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); @@ -509,25 +357,25 @@ METHOD(pts_component_t, measure, status_t, switch (this->state) { case IMA_STATE_INIT: - if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS, - this->bios_list, &this->measurement_time)) + 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->remove_first(this->bios_list, - (void**)&bios_entry); + 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, bios_entry->pcr, - bios_entry->measurement); - free(bios_entry); + evid = extend_pcr(this, qualifier, pcrs, pcr, measurement); this->state = this->bios_list->get_count(this->bios_list) ? IMA_STATE_BIOS : IMA_STATE_INIT; @@ -542,17 +390,20 @@ METHOD(pts_component_t, measure, status_t, switch (this->state) { case IMA_STATE_INIT: - if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS, - this->ima_list, &this->measurement_time)) + 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->remove_first(this->ima_list, - (void**)&ima_entry); + status = this->ima_list->get_next(this->ima_list, &measurement, + &algo, &name); if (status != SUCCESS) { DBG1(DBG_PTS, "could not retrieve ima measurement entry"); @@ -560,20 +411,33 @@ METHOD(pts_component_t, measure, status_t, } if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count) { - if (!check_boot_aggregate(pcrs, ima_entry->measurement)) + if (!check_boot_aggregate(pcrs, measurement, algo)) { return FAILED; } } evid = extend_pcr(this, qualifier, pcrs, IMA_PCR, - ima_entry->measurement); + 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, - ima_entry->filename); + uri); + free(uri); } - free(ima_entry->filename); - free(ima_entry); + free(name); + free(algo); this->state = this->ima_list->get_count(this->ima_list) ? IMA_STATE_RUNTIME : IMA_STATE_END; @@ -598,40 +462,80 @@ METHOD(pts_component_t, measure, status_t, SUCCESS : NEED_MORE; } -METHOD(pts_component_t, verify, status_t, - pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts, - pts_comp_evidence_t *evidence) +/** + * 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) { - bool has_pcr_info; - u_int32_t 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; - char *uri; + pts_meas_algorithms_t hash_algo; + char *uri, *pos, *algo, *name; - /* some first time initializations */ - if (!this->keyid.ptr) + evidence->get_validation(evidence, &uri); + + /* IMA-NG format? */ + pos = strchr(uri, ':'); + if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX) { - if (!pts->get_aik_keyid(pts, &this->keyid)) + 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:")) { - DBG1(DBG_PTS, "AIK keyid not available"); - return FAILED; + hash_algo = PTS_MEAS_ALGO_SHA256; } - this->keyid = chunk_clone(this->keyid); - if (!this->pts_db) + else if (streq(algo, "sha384:")) { - DBG1(DBG_PTS, "pts database not available"); - return FAILED; + 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, - &measurement_time); + &creation_time); if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | PTS_ITA_QUALIFIER_TYPE_TRUSTED)) @@ -641,26 +545,22 @@ METHOD(pts_component_t, verify, status_t, 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->keyid, algo, &this->bios_cid, - &this->kid, &this->bios_count); + 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; } - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); if (this->bios_count) { - DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements", - this->bios_count, pen_names, vid, names, name); + DBG1(DBG_PTS, "checking %d BIOS evidence measurements", + this->bios_count); } else { - DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements", - pen_names, vid, names, name); + DBG1(DBG_PTS, "registering BIOS evidence measurements"); this->is_bios_registering = TRUE; } @@ -670,8 +570,8 @@ METHOD(pts_component_t, verify, status_t, if (this->is_bios_registering) { status = this->pts_db->insert_comp_measurement(this->pts_db, - measurement, this->bios_cid, this->kid, - ++this->seq_no, pcr, algo); + measurement, this->bios_cid, this->aik_id, + ++this->seq_no, pcr, algo); if (status != SUCCESS) { return status; @@ -681,8 +581,8 @@ METHOD(pts_component_t, verify, status_t, else { status = this->pts_db->check_comp_measurement(this->pts_db, - measurement, this->bios_cid, this->kid, - ++this->seq_no, pcr, algo); + measurement, this->bios_cid, this->aik_id, + ++this->seq_no, pcr, algo); if (status == FAILED) { return status; @@ -697,13 +597,34 @@ METHOD(pts_component_t, verify, status_t, 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: - if (!check_boot_aggregate(pcrs, measurement)) + 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)) { - this->state = IMA_STATE_RUNTIME; return FAILED; } this->state = IMA_STATE_INIT; @@ -711,33 +632,30 @@ METHOD(pts_component_t, verify, status_t, 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->keyid, algo, - &this->ima_cid, &this->kid, &ima_count); + 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; } - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); if (ima_count) { - DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence " - "measurement", pen_names, vid, names, name); + DBG1(DBG_PTS, "checking boot aggregate evidence " + "measurement"); status = this->pts_db->check_comp_measurement(this->pts_db, measurement, this->ima_cid, - this->kid, 1, pcr, algo); + this->aik_id, 1, pcr, algo); } else { - DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence " - "measurement", pen_names, vid, names, name); + 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->kid, 1, pcr, algo); + this->aik_id, 1, pcr, algo); } this->state = IMA_STATE_RUNTIME; @@ -747,42 +665,76 @@ METHOD(pts_component_t, verify, status_t, } 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, &uri) != + if (evidence->get_validation(evidence, NULL) != PTS_COMP_EVID_VALIDATION_PASSED) { - DBG1(DBG_PTS, "policy URI could no be retrieved"); + DBG1(DBG_PTS, "evidence validation failed"); this->count_failed++; return FAILED; } - status = this->pts_db->check_file_measurement(this->pts_db, - pts->get_platform_info(pts), - PTS_MEAS_ALGO_SHA1_IMA, - measurement, uri); + 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, uri); + &measurement, ima_name); this->count_ok++; break; case NOT_FOUND: DBG2(DBG_PTS, "%#B for '%s' not found", - &measurement, uri); + &measurement, ima_name); this->count_unknown++; break; case VERIFY_ERROR: DBG1(DBG_PTS, "%#B for '%s' differs", - &measurement, uri); + &measurement, ima_name); this->count_differ++; break; case FAILED: default: DBG1(DBG_PTS, "%#B for '%s' failed", - &measurement, uri); + &measurement, ima_name); this->count_failed++; } break; + } default: return FAILED; } @@ -818,16 +770,15 @@ METHOD(pts_component_t, verify, status_t, } METHOD(pts_component_t, finalize, bool, - pts_ita_comp_ima_t *this, u_int8_t qualifier) + pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result) { - u_int32_t vid, name; - enum_name_t *names; + 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); - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | PTS_ITA_QUALIFIER_TYPE_TRUSTED)) @@ -838,16 +789,20 @@ METHOD(pts_component_t, finalize, bool, /* close registration */ this->is_bios_registering = FALSE; - DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements", - this->seq_no, pen_names, vid, names, name); + snprintf(pos, len, "registered %d BIOS evidence measurements", + this->seq_no); } else if (this->seq_no < this->bios_count) { - DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing", - this->bios_count - this->seq_no, this->bios_count, - pen_names, vid, names, name); + 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)) @@ -858,26 +813,34 @@ METHOD(pts_component_t, finalize, bool, /* close registration */ this->is_ima_registering = FALSE; - DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence " - "measurement", pen_names, vid, names, name); + written = snprintf(pos, len, "registered IMA boot aggregate " + "evidence measurement; "); + pos += written; + len -= written; } if (this->count) { - DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: " - "%d ok, %d unknown, %d differ, %d failed", - this->count, pen_names, vid, names, name, - this->count_ok, this->count_unknown, - this->count_differ, this->count_failed); - success = !this->count_differ && !this->count_failed; + 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 { - DBG1(DBG_PTS, "unsupported functional component name qualifier"); + 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; } @@ -892,35 +855,28 @@ METHOD(pts_component_t, destroy, void, pts_ita_comp_ima_t *this) { int count; - u_int32_t vid, name; - enum_name_t *names; if (ref_put(&this->ref)) { - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); if (this->is_bios_registering) { count = this->pts_db->delete_comp_measurements(this->pts_db, - this->bios_cid, this->kid); - DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence " - "measurements", count, pen_names, vid, names, name); + 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->kid); - DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence " - "measurement", pen_names, vid, names, name); + this->ima_cid, this->aik_id); + DBG1(DBG_PTS, "deleted registered boot aggregate evidence " + "measurement"); } - this->bios_list->destroy_function(this->bios_list, - (void *)free_bios_entry); - this->ima_list->destroy_function(this->ima_list, - (void *)free_ima_entry); + DESTROY_IF(this->bios_list); + DESTROY_IF(this->ima_list); this->name->destroy(this->name); - free(this->keyid.ptr); + free(this); } } @@ -928,7 +884,7 @@ METHOD(pts_component_t, destroy, void, /** * See header */ -pts_component_t *pts_ita_comp_ima_create(u_int32_t depth, +pts_component_t *pts_ita_comp_ima_create(uint32_t depth, pts_database_t *pts_db) { pts_ita_comp_ima_t *this; @@ -948,10 +904,8 @@ pts_component_t *pts_ita_comp_ima_create(u_int32_t depth, PTS_QUALIFIER_UNKNOWN), .depth = depth, .pts_db = pts_db, - .bios_list = linked_list_create(), - .ima_list = linked_list_create(), .pcr_info = lib->settings->get_bool(lib->settings, - "%s.plugins.imc-attestation.pcr_info", TRUE, lib->ns), + "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns), .ref = 1, ); diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c index f4859f801..67be1ca3a 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.c +++ b/src/libpts/pts/components/ita/ita_comp_tboot.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -41,11 +41,6 @@ struct pts_ita_comp_tboot_t { pts_comp_func_name_t *name; /** - * AIK keyid - */ - chunk_t keyid; - - /** * Sub-component depth */ u_int32_t depth; @@ -56,6 +51,11 @@ struct pts_ita_comp_tboot_t { pts_database_t *pts_db; /** + * Primary key for AIK database entry + */ + int aik_id; + + /** * Primary key for Component Functional Name database entry */ int cid; @@ -201,51 +201,38 @@ METHOD(pts_component_t, verify, status_t, 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); - if (!this->keyid.ptr) + status = this->pts_db->get_comp_measurement_count(this->pts_db, + this->name, this->aik_id, algo, + &this->cid, &this->count); + if (status != SUCCESS) { - if (!pts->get_aik_keyid(pts, &this->keyid)) - { - return FAILED; - } - this->keyid = chunk_clone(this->keyid); - - if (!this->pts_db) - { - DBG1(DBG_PTS, "pts database not available"); - return FAILED; - } - status = this->pts_db->get_comp_measurement_count(this->pts_db, - this->name, this->keyid, algo, &this->cid, - &this->kid, &this->count); - if (status != SUCCESS) - { - return status; - } - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); + return status; + } + vid = this->name->get_vendor_id(this->name); + name = this->name->get_name(this->name); + names = pts_components->get_comp_func_names(pts_components, vid); - if (this->count) - { - DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence " - "measurements", this->count, pen_names, vid, names, name); - } - else - { - DBG1(DBG_PTS, "registering %N '%N' functional component evidence " - "measurements", pen_names, vid, names, name); - this->is_registering = TRUE; - } + if (this->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->kid, + measurement, this->cid, this->aik_id, ++this->seq_no, extended_pcr, algo); if (status != SUCCESS) { @@ -282,30 +269,31 @@ METHOD(pts_component_t, verify, status_t, } METHOD(pts_component_t, finalize, bool, - pts_ita_comp_tboot_t *this, u_int8_t qualifier) + pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result) { - u_int32_t vid, name; - enum_name_t *names; - - vid = this->name->get_vendor_id(this->name); - name = this->name->get_name(this->name); - names = pts_components->get_comp_func_names(pts_components, vid); + char result_buf[BUF_LEN]; if (this->is_registering) { /* close registration */ this->is_registering = FALSE; - DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence " - "measurements", this->seq_no, pen_names, vid, names, name); + snprintf(result_buf, BUF_LEN, "registered %d evidence measurements", + this->seq_no); } else if (this->seq_no < this->count) { - DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence " - "measurements missing", this->count - this->seq_no, - this->count, pen_names, vid, names, name); + 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; } @@ -329,7 +317,7 @@ METHOD(pts_component_t, destroy, void, if (this->is_registering) { count = this->pts_db->delete_comp_measurements(this->pts_db, - this->cid, this->kid); + this->cid, this->aik_id); vid = this->name->get_vendor_id(this->name); name = this->name->get_name(this->name); names = pts_components->get_comp_func_names(pts_components, vid); @@ -337,7 +325,6 @@ METHOD(pts_component_t, destroy, void, "evidence measurements", count, pen_names, vid, names, name); } this->name->destroy(this->name); - free(this->keyid.ptr); free(this); } } diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c index e3acd8774..097e4c89c 100644 --- a/src/libpts/pts/components/ita/ita_comp_tgrub.c +++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c @@ -49,7 +49,6 @@ struct pts_ita_comp_tgrub_t { */ pts_database_t *pts_db; - /** * Reference count */ @@ -126,7 +125,8 @@ METHOD(pts_component_t, verify, status_t, pts_pcr_transform_t transform; pts_pcr_t *pcrs; time_t measurement_time; - chunk_t measurement, pcr_before, pcr_after; + chunk_t pcr_before, pcr_after; + chunk_t measurement __attribute__((unused)); pcrs = pts->get_pcrs(pts); measurement = evidence->get_measurement(evidence, &extended_pcr, @@ -155,7 +155,7 @@ METHOD(pts_component_t, verify, status_t, } METHOD(pts_component_t, finalize, bool, - pts_ita_comp_tgrub_t *this, u_int8_t qualifier) + pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result) { return FALSE; } @@ -206,4 +206,3 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth, return &this->public; } - diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h index da339a55f..71b1ad59c 100644 --- a/src/libpts/pts/components/pts_component.h +++ b/src/libpts/pts/components/pts_component.h @@ -30,6 +30,7 @@ typedef struct pts_component_t pts_component_t; #include "pts/components/pts_comp_evidence.h" #include <library.h> +#include <bio/bio_writer.h> /** * PTS Functional Component Interface @@ -85,9 +86,11 @@ struct pts_component_t { * 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); + bool (*finalize)(pts_component_t *this, u_int8_t qualifier, + bio_writer_t *result); /** * Get a new reference to the PTS Functional Component diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 3ab9b92e6..2fff4c901 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * 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 @@ -21,6 +22,10 @@ #include <bio/bio_reader.h> #ifdef TSS_TROUSERS +#ifdef _BASETSD_H_ +/* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */ +# define _BASETSD_H +#endif #include <trousers/tss.h> #include <trousers/trousers.h> #else @@ -34,7 +39,6 @@ #include <sys/types.h> #include <sys/stat.h> -#include <sys/utsname.h> #include <libgen.h> #include <unistd.h> #include <errno.h> @@ -88,9 +92,9 @@ struct private_pts_t { chunk_t secret; /** - * Platform and OS Info + * Primary key of platform entry in database */ - char *platform_info; + int platform_id; /** * TRUE if IMC-PTS, FALSE if IMV-PTS @@ -118,6 +122,11 @@ struct private_pts_t { certificate_t *aik; /** + * Primary key referening AIK in database + */ + int aik_id; + + /** * Shadow PCR set */ pts_pcr_t *pcrs; @@ -296,29 +305,23 @@ METHOD(pts_t, calculate_secret, bool, */ static void print_tpm_version_info(private_pts_t *this) { - TPM_CAP_VERSION_INFO versionInfo; - UINT64 offset = 0; - TSS_RESULT result; + TPM_CAP_VERSION_INFO *info; - result = Trspi_UnloadBlob_CAP_VERSION_INFO(&offset, - this->tpm_version_info.ptr, &versionInfo); - if (result != TSS_SUCCESS) + info = (TPM_CAP_VERSION_INFO*)this->tpm_version_info.ptr; + + if (this->tpm_version_info.len >= + sizeof(*info) - sizeof(info->vendorSpecific)) { - DBG1(DBG_PTS, "could not parse tpm version info: tss error 0x%x", - result); + DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, " + "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s", + info->version.major, info->version.minor, + info->version.revMajor, info->version.revMinor, + untoh16(&info->specLevel), info->errataRev, info->tpmVendorID); } else { - DBG2(DBG_PTS, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu," - " Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s [%.*s]", - versionInfo.version.major, versionInfo.version.minor, - versionInfo.version.revMajor, versionInfo.version.revMinor, - versionInfo.specLevel, versionInfo.errataRev, - versionInfo.tpmVendorID, versionInfo.vendorSpecificSize, - versionInfo.vendorSpecificSize ? - (char*)versionInfo.vendorSpecific : ""); + DBG1(DBG_PTS, "could not parse tpm version info"); } - free(versionInfo.vendorSpecific); } #else @@ -330,22 +333,16 @@ static void print_tpm_version_info(private_pts_t *this) #endif /* TSS_TROUSERS */ -METHOD(pts_t, get_platform_info, char*, +METHOD(pts_t, get_platform_id, int, private_pts_t *this) { - return this->platform_info; + return this->platform_id; } -METHOD(pts_t, set_platform_info, void, - private_pts_t *this, chunk_t name, chunk_t version) +METHOD(pts_t, set_platform_id, void, + private_pts_t *this, int pid) { - int len = name.len + 1 + version.len + 1; - - /* platform info is a concatenation of OS name and OS version */ - free(this->platform_info); - this->platform_info = malloc(len); - snprintf(this->platform_info, len, "%.*s %.*s", (int)name.len, name.ptr, - (int)version.len, version.ptr); + this->platform_id = pid; } METHOD(pts_t, get_tpm_version_info, bool, @@ -372,42 +369,31 @@ METHOD(pts_t, set_tpm_version_info, void, */ static void load_aik_blob(private_pts_t *this) { - char *blob_path; - FILE *fp; - u_int32_t aikBlobLen; + char *path; + chunk_t *map; - blob_path = lib->settings->get_str(lib->settings, + path = lib->settings->get_str(lib->settings, "%s.plugins.imc-attestation.aik_blob", NULL, lib->ns); - - if (blob_path) + if (path) { - /* Read aik key blob from a file */ - if ((fp = fopen(blob_path, "r")) == NULL) - { - DBG1(DBG_PTS, "unable to open AIK Blob file: %s", blob_path); - return; - } - - fseek(fp, 0, SEEK_END); - aikBlobLen = ftell(fp); - fseek(fp, 0L, SEEK_SET); - - this->aik_blob = chunk_alloc(aikBlobLen); - if (fread(this->aik_blob.ptr, 1, aikBlobLen, fp) == aikBlobLen) + map = chunk_map(path, FALSE); + if (map) { - DBG2(DBG_PTS, "loaded AIK Blob from '%s'", blob_path); - DBG3(DBG_PTS, "AIK Blob: %B", &this->aik_blob); + DBG2(DBG_PTS, "loaded AIK Blob from '%s'", path); + DBG3(DBG_PTS, "AIK Blob: %B", map); + this->aik_blob = chunk_clone(*map); + chunk_unmap(map); } else { - DBG1(DBG_PTS, "unable to read AIK Blob file '%s'", blob_path); - chunk_free(&this->aik_blob); + DBG1(DBG_PTS, "unable to map AIK Blob file '%s': %s", + path, strerror(errno)); } - fclose(fp); - return; } - - DBG1(DBG_PTS, "AIK Blob is not available"); + else + { + DBG1(DBG_PTS, "AIK Blob is not available"); + } } /** @@ -421,7 +407,7 @@ static void load_aik(private_pts_t *this) cert_path = lib->settings->get_str(lib->settings, "%s.plugins.imc-attestation.aik_cert", NULL, lib->ns); key_path = lib->settings->get_str(lib->settings, - "%s.plugins.imc-attestation.aik_key", NULL, lib->ns); + "%s.plugins.imc-attestation.aik_pubkey", NULL, lib->ns); if (cert_path) { @@ -456,37 +442,17 @@ METHOD(pts_t, get_aik, certificate_t*, } METHOD(pts_t, set_aik, void, - private_pts_t *this, certificate_t *aik) + private_pts_t *this, certificate_t *aik, int aik_id) { DESTROY_IF(this->aik); this->aik = aik->get_ref(aik); + this->aik_id = aik_id; } -METHOD(pts_t, get_aik_keyid, bool, - private_pts_t *this, chunk_t *keyid) +METHOD(pts_t, get_aik_id, int, + private_pts_t *this) { - public_key_t *public; - bool success; - - if (!this->aik) - { - DBG1(DBG_PTS, "no AIK certificate available"); - return FALSE; - } - public = this->aik->get_public_key(this->aik); - if (!public) - { - DBG1(DBG_PTS, "no AIK public key available"); - return FALSE; - } - success = public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, keyid); - if (!success) - { - DBG1(DBG_PTS, "no SHA-1 AIK public key info ID available"); - } - public->destroy(public); - - return success; + return this->aik_id; } METHOD(pts_t, is_path_valid, bool, @@ -557,6 +523,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry) { this->type = PTS_FILE_FIFO; } +#ifndef WIN32 else if (S_ISLNK(st.st_mode)) { this->type = PTS_FILE_SYM_LINK; @@ -565,6 +532,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry) { this->type = PTS_FILE_SOCKET; } +#endif /* WIN32 */ else { this->type = PTS_FILE_OTHER; @@ -644,7 +612,8 @@ METHOD(pts_t, read_pcr, bool, TSS_HCONTEXT hContext; TSS_HTPM hTPM; TSS_RESULT result; - chunk_t rgbPcrValue; + BYTE *buf; + UINT32 len; bool success = FALSE; @@ -665,12 +634,12 @@ METHOD(pts_t, read_pcr, bool, { goto err; } - result = Tspi_TPM_PcrRead(hTPM, pcr_num, (UINT32*)&rgbPcrValue.len, &rgbPcrValue.ptr); + result = Tspi_TPM_PcrRead(hTPM, pcr_num, &len, &buf); if (result != TSS_SUCCESS) { goto err; } - *pcr_value = chunk_clone(rgbPcrValue); + *pcr_value = chunk_clone(chunk_create(buf, len)); DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, pcr_value); success = TRUE; @@ -1093,7 +1062,6 @@ METHOD(pts_t, destroy, void, free(this->initiator_nonce.ptr); free(this->responder_nonce.ptr); free(this->secret.ptr); - free(this->platform_info); free(this->aik_blob.ptr); free(this->tpm_version_info.ptr); free(this); @@ -1187,13 +1155,13 @@ pts_t *pts_create(bool is_imc) .get_my_public_value = _get_my_public_value, .set_peer_public_value = _set_peer_public_value, .calculate_secret = _calculate_secret, - .get_platform_info = _get_platform_info, - .set_platform_info = _set_platform_info, + .get_platform_id = _get_platform_id, + .set_platform_id = _set_platform_id, .get_tpm_version_info = _get_tpm_version_info, .set_tpm_version_info = _set_tpm_version_info, .get_aik = _get_aik, .set_aik = _set_aik, - .get_aik_keyid = _get_aik_keyid, + .get_aik_id = _get_aik_id, .is_path_valid = _is_path_valid, .get_metadata = _get_metadata, .read_pcr = _read_pcr, diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index 11154aa38..fead588ae 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -1,5 +1,6 @@ /* * 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 @@ -162,19 +163,18 @@ struct pts_t { bool (*calculate_secret) (pts_t *this); /** - * Get Platform and OS Info + * Get primary key of platform entry in database * * @return Platform and OS info */ - char* (*get_platform_info)(pts_t *this); + int (*get_platform_id)(pts_t *this); /** - * Set Platform and OS Info + * Set primary key of platform entry in database * - * @param name OS name - * @param version OS version + * @param pid Primary key of platform entry in database */ - void (*set_platform_info)(pts_t *this, chunk_t name, chunk_t version); + void (*set_platform_id)(pts_t *this, int pid); /** * Get TPM 1.2 Version Info @@ -202,16 +202,16 @@ struct pts_t { * 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); + void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id); /** - * Get SHA-1 Attestation Identity Public Key Info ID + * Get primary key referencing AIK in database * - * @param keyid AIK ID - * @return TRUE if AIK ID exists + * @return Primary key referencing AIK in database */ - bool (*get_aik_keyid)(pts_t *this, chunk_t *keyid); + int (*get_aik_id)(pts_t *this); /** * Check whether path is valid file/directory on filesystem diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c index fda644a6a..d7b85c138 100644 --- a/src/libpts/pts/pts_database.c +++ b/src/libpts/pts/pts_database.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * 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 @@ -47,7 +48,7 @@ METHOD(pts_database_t, get_pathname, char*, private_pts_database_t *this, bool is_dir, int id) { enumerator_t *e; - char *path, *name, *pathname; + char *path, *name, *sep, *pathname = NULL; if (is_dir) { @@ -69,11 +70,21 @@ METHOD(pts_database_t, get_pathname, char*, "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) || - asprintf(&pathname, "%s%s%s", - path, streq(path, "/") ? "" : "/", name) == -1) + if (e && e->enumerate(e, &path, &name)) { - pathname = NULL; + 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); @@ -82,7 +93,7 @@ METHOD(pts_database_t, get_pathname, char*, } METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*, - private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, + private_pts_database_t *this, int pid, pts_meas_algorithms_t algo, bool is_dir, int id) { enumerator_t *e; @@ -90,73 +101,34 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*, if (is_dir) { e = this->db->query(this->db, - "SELECT f.name, fh.hash FROM file_hashes AS fh " + "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh " "JOIN files AS f ON f.id = fh.file " - "JOIN products AS p ON p.id = fh.product " "JOIN directories as d ON d.id = f.dir " - "WHERE p.name = ? AND fh.algo = ? AND d.id = ? " + "WHERE fh.product = ? AND fh.algo = ? AND d.id = ? " "ORDER BY f.name", - DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB); + DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB); } else { e = this->db->query(this->db, - "SELECT f.name, fh.hash FROM file_hashes AS fh " + "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh " "JOIN files AS f ON f.id = fh.file " - "JOIN products AS p ON p.id = fh.product " - "WHERE p.name = ? AND fh.algo = ? AND fh.file = ?", - DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB); + "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, check_aik_keyid, status_t, - private_pts_database_t *this, chunk_t keyid, int *kid) -{ - enumerator_t *e; - - /* If the AIK is registered get the primary key */ - e = this->db->query(this->db, - "SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT); - if (!e) - { - DBG1(DBG_PTS, "no database query enumerator returned"); - return FAILED; - } - if (!e->enumerate(e, kid)) - { - DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid); - e->destroy(e); - return FAILED; - } - e->destroy(e); - - return SUCCESS; -} - METHOD(pts_database_t, add_file_measurement, status_t, - private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, + 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, pid = 0; + int hash_id, fid; status_t status = SUCCESS; - /* get primary key of product string */ - e = this->db->query(this->db, - "SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT); - if (e) - { - e->enumerate(e, &pid); - e->destroy(e); - } - if (pid == 0) - { - return FAILED; - } - if (is_dir) { /* does filename entry already exist? */ @@ -242,18 +214,16 @@ METHOD(pts_database_t, add_file_measurement, status_t, return status; } -METHOD(pts_database_t, check_file_measurement, status_t, - private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, - chunk_t measurement, char *filename) +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; - chunk_t hash; - status_t status = NOT_FOUND; char *dir, *file; if (strlen(filename) < 1) { - return INVALID_ARG; + return NULL; } /* separate filename into directory and basename components */ @@ -265,84 +235,40 @@ METHOD(pts_database_t, check_file_measurement, status_t, e = this->db->query(this->db, "SELECT fh.hash FROM file_hashes AS fh " "JOIN files AS f ON f.id = fh.file " - "JOIN products AS p ON p.id = fh.product " - "WHERE p.name = ? AND f.name = ? AND fh.algo = ?", - DB_TEXT, product, DB_TEXT, file, DB_INT, algo, DB_BLOB); + "WHERE fh.product = ? AND f.name = ? AND fh.algo = ?", + DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB); } else { /* absolute pathname */ - bool dir_found; 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) + + if (!e || !e->enumerate(e, &did)) { - status = FAILED; goto err; } - dir_found = e->enumerate(e, &did); e->destroy(e); - if (!dir_found) - { - status = NOT_FOUND; - goto err; - } e = this->db->query(this->db, "SELECT fh.hash FROM file_hashes AS fh " "JOIN files AS f ON f.id = fh.file " - "JOIN products AS p ON p.id = fh.product " - "WHERE p.name = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?", - DB_TEXT, product, DB_INT, did, DB_TEXT, file, DB_INT, algo, - DB_BLOB); - } - if (!e) - { - status = FAILED; - goto err; + "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); } - while (e->enumerate(e, &hash)) - { - /* with relative filenames there might be multiple entries */ - if (chunk_equals(measurement, hash)) - { - status = SUCCESS; - break; - } - else - { - status = VERIFY_ERROR; - } - } - e->destroy(e); err: free(file); free(dir); - return status; -} - -METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*, - private_pts_database_t *this, int kid) -{ - enumerator_t *e; - - /* look for all entries belonging to an AIK in the components table */ - e = this->db->query(this->db, - "SELECT c.vendor_id, c.name, c.qualifier, kc.depth " - "FROM components AS c " - "JOIN key_component AS kc ON c.id = kc.component " - "WHERE kc.key = ? ORDER BY kc.seq_no", - DB_INT, kid, DB_INT, DB_INT, DB_INT, DB_INT); return e; } METHOD(pts_database_t, check_comp_measurement, status_t, - private_pts_database_t *this, chunk_t measurement, int cid, int kid, + 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; @@ -353,7 +279,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t, "SELECT hash FROM component_hashes " "WHERE component = ? AND key = ? " "AND seq_no = ? AND pcr = ? AND algo = ? ", - DB_INT, cid, DB_INT, kid, DB_INT, seq_no, + DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr, DB_INT, algo, DB_BLOB); if (!e) { @@ -390,7 +316,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t, } METHOD(pts_database_t, insert_comp_measurement, status_t, - private_pts_database_t *this, chunk_t measurement, int cid, int kid, + 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; @@ -399,7 +325,7 @@ METHOD(pts_database_t, insert_comp_measurement, status_t, "INSERT INTO component_hashes " "(component, key, seq_no, pcr, algo, hash) " "VALUES (?, ?, ?, ?, ?, ?)", - DB_INT, cid, DB_INT, kid, DB_INT, seq_no, DB_INT, pcr, + DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr, DB_INT, algo, DB_BLOB, measurement) == 1) { return SUCCESS; @@ -410,17 +336,17 @@ METHOD(pts_database_t, insert_comp_measurement, status_t, } METHOD(pts_database_t, delete_comp_measurements, int, - private_pts_database_t *this, int cid, int kid) + 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, kid); + 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, - chunk_t keyid, pts_meas_algorithms_t algo, int *cid, int *kid, int *count) + int aik_id, pts_meas_algorithms_t algo, int *cid, int *count) { enumerator_t *e; status_t status = SUCCESS; @@ -428,11 +354,6 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t, /* Initialize count */ *count = 0; - if (_check_aik_keyid(this, keyid, kid) != SUCCESS) - { - return FAILED; - } - /* Get the primary key of the Component Functional Name */ e = this->db->query(this->db, "SELECT id FROM components " @@ -458,7 +379,7 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t, e = this->db->query(this->db, "SELECT COUNT(*) FROM component_hashes AS ch " "WHERE component = ? AND key = ? AND algo = ?", - DB_INT, *cid, DB_INT, *kid, DB_INT, algo, DB_INT); + DB_INT, *cid, DB_INT, aik_id, DB_INT, algo, DB_INT); if (!e) { DBG1(DBG_PTS, "no database query enumerator returned"); @@ -495,11 +416,9 @@ pts_database_t *pts_database_create(imv_database_t *imv_db) INIT(this, .public = { .get_pathname = _get_pathname, - .create_comp_evid_enumerator = _create_comp_evid_enumerator, .create_file_hash_enumerator = _create_file_hash_enumerator, - .check_aik_keyid = _check_aik_keyid, .add_file_measurement = _add_file_measurement, - .check_file_measurement = _check_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, @@ -511,4 +430,3 @@ pts_database_t *pts_database_create(imv_database_t *imv_db) return &this->public; } - diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h index eb8aca346..a6c9fb3b6 100644 --- a/src/libpts/pts/pts_database.h +++ b/src/libpts/pts/pts_database.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -47,37 +47,20 @@ struct pts_database_t { /** * Get stored measurement hash for single file or directory entries * - * @param product Software product (os, vpn client, etc.) + * @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, - char *product, pts_meas_algorithms_t algo, + int pid, pts_meas_algorithms_t algo, bool is_dir, int id); /** - * Check if an AIK given by its keyid is registered in the database - * - * @param keyid AIK keyid (SHA-1 hash of the AIK public key info) - * @param kid Primary key of AIK entry in keys table - * @return SUCCESS if AIK is present, FAILED otherwise - */ - status_t (*check_aik_keyid)(pts_database_t *this, chunk_t keyid, int *kid); - - /** - * Get functional components to request evidence of - * - * @param kid Primary key of AIK entry in keys table - * @return Enumerator over all matching components - */ - enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid); - - /** * Add PTS file measurement reference value * - * @param product Software product (os, vpn client, etc.) + * @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 @@ -85,37 +68,36 @@ struct pts_database_t { * @param id Primary key into direcories/files table * @return Status */ - status_t (*add_file_measurement)(pts_database_t *this, char *product, + 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); /** - * Check PTS file measurement against reference stored in database + * Get PTS measurement[s] for a given filename stored in database * - * @param product Software product (os, vpn client, etc.) + * @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 - * @return Status + * @param filename Name of the file to be checked + * @return Enumerator over all matching measurement hashes */ - status_t (*check_file_measurement)(pts_database_t *this, char *product, - pts_meas_algorithms_t algo, - chunk_t measurement, char *filename); + 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 kid Primary key of AIK entry in keys table + * @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 kid, int seq_no, int pcr, + int cid, int aik_id, int seq_no, int pcr, pts_meas_algorithms_t algo); /** @@ -123,40 +105,38 @@ struct pts_database_t { * * @param measurement Measurement hash * @param cid Primary key of Component Functional Name entry - * @param kid Primary key of AIK entry in keys table + * @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 kid, int seq_no, int pcr, + 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 kid Primary key of AIK entry in keys table + * @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 kid); + 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 keyid SHA-1 hash of AIK public key info + * @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 kid Primary key of AIK entry in keys table * @param count measurement count * @return SUCCESS if COUNT was successful */ status_t (*get_comp_measurement_count)(pts_database_t *this, - pts_comp_func_name_t *comp_name, chunk_t keyid, - pts_meas_algorithms_t algo, int *cid, int *kid, - int *count); + 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. diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c index 77a0957bb..478892aea 100644 --- a/src/libpts/pts/pts_file_meas.c +++ b/src/libpts/pts/pts_file_meas.c @@ -1,5 +1,6 @@ /* * 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 @@ -112,19 +113,43 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*, } METHOD(pts_file_meas_t, check, bool, - private_pts_file_meas_t *this, pts_database_t *pts_db, char *product, + private_pts_file_meas_t *this, pts_database_t *pts_db, int pid, pts_meas_algorithms_t algo) { - enumerator_t *enumerator; + 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 = pts_db->check_file_measurement(pts_db, product, algo, - entry->measurement, entry->filename); + 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: @@ -159,47 +184,75 @@ METHOD(pts_file_meas_t, check, bool, 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; - bool found, success = TRUE; + enumerator_t *enumerator = NULL; + bool found = FALSE, match = FALSE, success = TRUE; - while (e_hash->enumerate(e_hash, &filename, &measurement)) + while (e_hash->enumerate(e_hash, &fid, &filename, &measurement)) { - found = FALSE; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &entry)) + if (fid != fid_last) { - if (!is_dir || streq(filename, entry->filename)) + if (found && !match) { - found = TRUE; - break; + /* 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); } - } - enumerator->destroy(enumerator); - if (!found) - { - DBG1(DBG_PTS, " no measurement found for '%s'", filename); - success = FALSE; - continue; - } - if (chunk_equals(measurement, entry->measurement)) - { - DBG2(DBG_PTS, " %#B for '%s' is ok", &measurement, filename); - } - else - { - DBG1(DBG_PTS, " %#B for '%s' is incorrect", &measurement, filename); - success = FALSE; + /* 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 (!is_dir) + + if (found && !match) { - break; + 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; } diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h index a13bb29ba..4bf28e280 100644 --- a/src/libpts/pts/pts_file_meas.h +++ b/src/libpts/pts/pts_file_meas.h @@ -1,5 +1,6 @@ /* * 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 @@ -65,11 +66,11 @@ struct pts_file_meas_t { * Check PTS File Measurements against reference value in the database * * @param db PTS Measurement database - * @param product Software product (os, vpn client, etc.) + * @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, char* product, + bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid, pts_meas_algorithms_t algo); /** diff --git a/src/libpts/pts/pts_ima_bios_list.c b/src/libpts/pts/pts_ima_bios_list.c new file mode 100644 index 000000000..5051b6c2d --- /dev/null +++ b/src/libpts/pts/pts_ima_bios_list.c @@ -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; +} diff --git a/src/libpts/pts/pts_ima_bios_list.h b/src/libpts/pts/pts_ima_bios_list.h new file mode 100644 index 000000000..ad162e15a --- /dev/null +++ b/src/libpts/pts/pts_ima_bios_list.h @@ -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_ @}*/ diff --git a/src/libpts/pts/pts_ima_event_list.c b/src/libpts/pts/pts_ima_event_list.c new file mode 100644 index 000000000..9bff4654b --- /dev/null +++ b/src/libpts/pts/pts_ima_event_list.c @@ -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; +} diff --git a/src/libpts/pts/pts_ima_event_list.h b/src/libpts/pts/pts_ima_event_list.h new file mode 100644 index 000000000..bf5478a51 --- /dev/null +++ b/src/libpts/pts/pts_ima_event_list.h @@ -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_ @}*/ diff --git a/src/libpts/pts/pts_meas_algo.c b/src/libpts/pts/pts_meas_algo.c index 16a66e7b3..c06371123 100644 --- a/src/libpts/pts/pts_meas_algo.c +++ b/src/libpts/pts/pts_meas_algo.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -28,10 +28,7 @@ ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256, ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA256, "SHA1"); -ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA, PTS_MEAS_ALGO_SHA1_IMA, - PTS_MEAS_ALGO_SHA1, - "SHA1-IMA"); -ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA); +ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1); /** * Described in header. diff --git a/src/libpts/pts/pts_meas_algo.h b/src/libpts/pts/pts_meas_algo.h index 27cdaea7e..eec7e7981 100644 --- a/src/libpts/pts/pts_meas_algo.h +++ b/src/libpts/pts/pts_meas_algo.h @@ -1,5 +1,6 @@ /* * 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 @@ -33,8 +34,7 @@ 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), - PTS_MEAS_ALGO_SHA1_IMA = (1<<16), /* internal use only */ + PTS_MEAS_ALGO_SHA1 = (1<<15) }; /** |