moved all shadow PCR stuff to the pts_pcr class

This commit is contained in:
Andreas Steffen
2012-07-21 15:58:13 +02:00
parent 3b7468b245
commit 4c02086241
8 changed files with 334 additions and 291 deletions
@@ -420,9 +420,6 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
/* Send buffered Simple Component Evidences */ /* Send buffered Simple Component Evidences */
while (attestation_state->next_evidence(attestation_state, &evid)) while (attestation_state->next_evidence(attestation_state, &evid))
{ {
pts->select_pcr(pts, evid->get_extended_pcr(evid));
/* Send Simple Component Evidence */
attr = tcg_pts_attr_simple_comp_evid_create(evid); attr = tcg_pts_attr_simple_comp_evid_create(evid);
attr_list->insert_last(attr_list, attr); attr_list->insert_last(attr_list, attr);
} }
+31 -30
View File
@@ -121,11 +121,6 @@ struct pts_ita_comp_ima_t {
*/ */
linked_list_t *ima_list; linked_list_t *ima_list;
/**
* Shadow PCR set
*/
pts_pcr_t *pcrs;
/** /**
* Whether to send pcr_before and pcr_after info * Whether to send pcr_before and pcr_after info
*/ */
@@ -361,8 +356,8 @@ static bool load_runtime_measurements(char *file, linked_list_t *list,
/** /**
* Extend measurement into PCR an create evidence * Extend measurement into PCR an create evidence
*/ */
static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr, static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, pts_pcr_t *pcrs,
chunk_t measurement) u_int32_t pcr, chunk_t measurement)
{ {
size_t pcr_len; size_t pcr_len;
pts_pcr_transform_t pcr_transform; pts_pcr_transform_t pcr_transform;
@@ -376,9 +371,9 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
if (this->pcr_info) if (this->pcr_info)
{ {
pcr_before = chunk_clone(this->pcrs->get(this->pcrs, pcr)); pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
} }
pcr_after = this->pcrs->extend(this->pcrs, pcr, measurement); pcr_after = pcrs->extend(pcrs, pcr, measurement);
if (!pcr_after.ptr) if (!pcr_after.ptr)
{ {
free(pcr_before.ptr); free(pcr_before.ptr);
@@ -389,7 +384,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
this->measurement_time, measurement); this->measurement_time, measurement);
if (this->pcr_info) if (this->pcr_info)
{ {
pcr_after =chunk_clone(this->pcrs->get(this->pcrs, pcr)); pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
evidence->set_pcr_info(evidence, pcr_before, pcr_after); evidence->set_pcr_info(evidence, pcr_before, pcr_after);
} }
return evidence; return evidence;
@@ -398,7 +393,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
/** /**
* Compute and check boot aggregate value by hashing PCR0 to PCR7 * Compute and check boot aggregate value by hashing PCR0 to PCR7
*/ */
static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement) static void check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
{ {
u_int32_t i; u_int32_t i;
u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1]; u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
@@ -415,7 +410,7 @@ static void check_boot_aggregate(pts_ita_comp_ima_t *this, chunk_t measurement)
} }
for (i = 0; i < 8 && pcr_ok; i++) for (i = 0; i < 8 && pcr_ok; i++)
{ {
pcr_ok = hasher->get_hash(hasher, this->pcrs->get(this->pcrs, i), NULL); pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
} }
if (pcr_ok) if (pcr_ok)
{ {
@@ -468,8 +463,10 @@ METHOD(pts_component_t, measure, status_t,
status_t status; status_t status;
int count; int count;
enumerator_t *e; enumerator_t *e;
pts_pcr_t *pcrs;
pts_file_meas_t *file_meas; pts_file_meas_t *file_meas;
pcrs = pts->get_pcrs(pts);
*measurements = NULL; *measurements = NULL;
switch (this->state) switch (this->state)
@@ -490,8 +487,8 @@ METHOD(pts_component_t, measure, status_t,
DBG1(DBG_PTS, "could not retrieve bios measurement entry"); DBG1(DBG_PTS, "could not retrieve bios measurement entry");
return status; return status;
} }
*evidence = extend_pcr(this, bios_entry->pcr, *evidence = extend_pcr(this, pcrs, bios_entry->pcr,
bios_entry->measurement); bios_entry->measurement);
free(bios_entry); free(bios_entry);
if (!evidence) if (!evidence)
{ {
@@ -545,11 +542,11 @@ METHOD(pts_component_t, measure, status_t,
DBG1(DBG_PTS, "could not retrieve ima measurement entry"); DBG1(DBG_PTS, "could not retrieve ima measurement entry");
return status; return status;
} }
*evidence = extend_pcr(this, IMA_PCR, ima_entry->measurement); *evidence = extend_pcr(this, pcrs, IMA_PCR, ima_entry->measurement);
if (this->state == IMA_STATE_BOOT_AGGREGATE) if (this->state == IMA_STATE_BOOT_AGGREGATE)
{ {
check_boot_aggregate(this, ima_entry->measurement); check_boot_aggregate(pcrs, ima_entry->measurement);
} }
free(ima_entry->file_measurement.ptr); free(ima_entry->file_measurement.ptr);
@@ -578,10 +575,12 @@ METHOD(pts_component_t, verify, status_t,
enum_name_t *names; enum_name_t *names;
pts_meas_algorithms_t algo; pts_meas_algorithms_t algo;
pts_pcr_transform_t transform; pts_pcr_transform_t transform;
pts_pcr_t *pcrs;
time_t measurement_time; time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after; chunk_t measurement, pcr_before, pcr_after;
status_t status; status_t status;
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr, measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time); &algo, &transform, &measurement_time);
@@ -665,13 +664,25 @@ METHOD(pts_component_t, verify, status_t,
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info) if (has_pcr_info)
{ {
if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{ {
return FAILED; DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value",
extended_pcr);
}
if (pcrs->set(pcrs, extended_pcr, pcr_after))
{
return SUCCESS;
} }
} }
else
return SUCCESS; {
pcr_after = pcrs->extend(pcrs, extended_pcr, measurement);
if (pcr_after.ptr)
{
return SUCCESS;
}
}
return FAILED;
} }
METHOD(pts_component_t, finalize, bool, METHOD(pts_component_t, finalize, bool,
@@ -723,7 +734,6 @@ METHOD(pts_component_t, destroy, void,
this->bios_list->destroy_function(this->bios_list, (void *)free_bios_entry); this->bios_list->destroy_function(this->bios_list, (void *)free_bios_entry);
this->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry); this->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry);
this->name->destroy(this->name); this->name->destroy(this->name);
this->pcrs->destroy(this->pcrs);
free(this->keyid.ptr); free(this->keyid.ptr);
free(this); free(this);
} }
@@ -735,14 +745,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
pts_database_t *pts_db) pts_database_t *pts_db)
{ {
pts_ita_comp_ima_t *this; pts_ita_comp_ima_t *this;
pts_pcr_t *pcrs;
pcrs = pts_pcr_create();
if (!pcrs)
{
DBG1(DBG_PTS, "shadow PCR set could not be created");
return NULL;
}
INIT(this, INIT(this,
.public = { .public = {
@@ -761,7 +763,6 @@ pts_component_t *pts_ita_comp_ima_create(u_int8_t qualifier, u_int32_t depth,
.bios_list = linked_list_create(), .bios_list = linked_list_create(),
.ima_list = linked_list_create(), .ima_list = linked_list_create(),
.ima_count = IMA_MEASUREMENT_BATCH_SIZE - 1, .ima_count = IMA_MEASUREMENT_BATCH_SIZE - 1,
.pcrs = pcrs,
.pcr_info = lib->settings->get_bool(lib->settings, .pcr_info = lib->settings->get_bool(lib->settings,
"libimcv.plugins.imc-attestation.pcr_info", TRUE), "libimcv.plugins.imc-attestation.pcr_info", TRUE),
); );
+20 -12
View File
@@ -110,13 +110,14 @@ METHOD(pts_component_t, measure, status_t,
pts_file_meas_t **measurements) pts_file_meas_t **measurements)
{ {
size_t pcr_len;
pts_pcr_t *pcrs;
pts_pcr_transform_t pcr_transform;
pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid; pts_comp_evidence_t *evid;
char *meas_hex, *pcr_before_hex, *pcr_after_hex; char *meas_hex, *pcr_before_hex, *pcr_after_hex;
chunk_t measurement, pcr_before, pcr_after; chunk_t measurement, pcr_before, pcr_after;
size_t hash_size, pcr_len;
u_int32_t extended_pcr; u_int32_t extended_pcr;
pts_pcr_transform_t pcr_transform;
pts_meas_algorithms_t hash_algo;
switch (this->seq_no++) switch (this->seq_no++)
{ {
@@ -150,9 +151,8 @@ METHOD(pts_component_t, measure, status_t,
return FAILED; return FAILED;
} }
hash_algo = pts->get_meas_algorithm(pts); hash_algo = PTS_MEAS_ALGO_SHA1;
hash_size = pts_meas_algo_hash_size(hash_algo); pcr_len = HASH_SIZE_SHA1;
pcr_len = pts->get_pcr_len(pts);
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
/* get and check the measurement data */ /* get and check the measurement data */
@@ -163,7 +163,7 @@ METHOD(pts_component_t, measure, status_t,
pcr_after = chunk_from_hex( pcr_after = chunk_from_hex(
chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL); chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
if (pcr_before.len != pcr_len || pcr_after.len != pcr_len || if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
measurement.len != hash_size) measurement.len != pcr_len)
{ {
DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size"); DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
free(measurement.ptr); free(measurement.ptr);
@@ -172,10 +172,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED; return FAILED;
} }
pcrs = pts->get_pcrs(pts);
pcrs->set(pcrs, extended_pcr, pcr_after);
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name), evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
this->depth, extended_pcr, this->depth, extended_pcr, hash_algo, pcr_transform,
hash_algo, pcr_transform, this->measurement_time, measurement);
this->measurement_time, measurement);
evid->set_pcr_info(evid, pcr_before, pcr_after); evid->set_pcr_info(evid, pcr_before, pcr_after);
return (this->seq_no < 2) ? NEED_MORE : SUCCESS; return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
@@ -189,10 +190,12 @@ METHOD(pts_component_t, verify, status_t,
enum_name_t *names; enum_name_t *names;
pts_meas_algorithms_t algo; pts_meas_algorithms_t algo;
pts_pcr_transform_t transform; pts_pcr_transform_t transform;
pts_pcr_t *pcrs;
time_t measurement_time; time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after; chunk_t measurement, pcr_before, pcr_after;
status_t status; status_t status;
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr, measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time); &algo, &transform, &measurement_time);
@@ -258,9 +261,14 @@ METHOD(pts_component_t, verify, status_t,
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info) if (has_pcr_info)
{ {
if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{ {
return FAILED; DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value",
extended_pcr);
}
if (pcrs->set(pcrs, extended_pcr, pcr_after))
{
return SUCCESS;
} }
} }
+14 -9
View File
@@ -73,13 +73,13 @@ METHOD(pts_component_t, measure, status_t,
pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence, pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence,
pts_file_meas_t **measurements) pts_file_meas_t **measurements)
{ {
size_t pcr_len;
pts_pcr_transform_t pcr_transform;
pts_meas_algorithms_t hash_algo;
pts_comp_evidence_t *evid; pts_comp_evidence_t *evid;
u_int32_t extended_pcr; u_int32_t extended_pcr;
time_t measurement_time; time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after; chunk_t measurement, pcr_before, pcr_after;
pts_pcr_transform_t pcr_transform;
pts_meas_algorithms_t hash_algo;
size_t hash_size, pcr_len;
/* Provisional implementation for TGRUB */ /* Provisional implementation for TGRUB */
extended_pcr = PCR_DEBUG; extended_pcr = PCR_DEBUG;
@@ -91,12 +91,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED; return FAILED;
} }
hash_algo = pts->get_meas_algorithm(pts); hash_algo = PTS_MEAS_ALGO_SHA1;
hash_size = pts_meas_algo_hash_size(hash_algo); pcr_len = HASH_SIZE_SHA1;
pcr_len = pts->get_pcr_len(pts);
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len); pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
measurement = chunk_alloc(hash_size); measurement = chunk_alloc(pcr_len);
memset(measurement.ptr, 0x00, measurement.len); memset(measurement.ptr, 0x00, measurement.len);
pcr_before = chunk_alloc(pcr_len); pcr_before = chunk_alloc(pcr_len);
@@ -118,9 +117,11 @@ METHOD(pts_component_t, verify, status_t,
u_int32_t extended_pcr; u_int32_t extended_pcr;
pts_meas_algorithms_t algo; pts_meas_algorithms_t algo;
pts_pcr_transform_t transform; pts_pcr_transform_t transform;
pts_pcr_t *pcrs;
time_t measurement_time; time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after; chunk_t measurement, pcr_before, pcr_after;
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr, measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time); &algo, &transform, &measurement_time);
if (extended_pcr != PCR_DEBUG) if (extended_pcr != PCR_DEBUG)
@@ -133,9 +134,13 @@ METHOD(pts_component_t, verify, status_t,
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after); has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info) if (has_pcr_info)
{ {
if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after)) if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
{ {
return FAILED; DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
}
if (pcrs->set(pcrs, extended_pcr, pcr_after))
{
return SUCCESS;
} }
} }
+40 -192
View File
@@ -30,16 +30,6 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
/**
* Maximum number of PCR's of TPM, TPM Spec 1.2
*/
#define PCR_MAX_NUM 24
/**
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
*/
#define PCR_LEN 20
typedef struct private_pts_t private_pts_t; typedef struct private_pts_t private_pts_t;
/** /**
@@ -119,29 +109,9 @@ struct private_pts_t {
certificate_t *aik; certificate_t *aik;
/** /**
* Table of extended PCRs with corresponding values * Shadow PCR set
*/ */
u_char* pcrs[PCR_MAX_NUM]; pts_pcr_t *pcrs;
/**
* Length of PCR registers
*/
size_t pcr_len;
/**
* Number of extended PCR registers
*/
u_int32_t pcr_count;
/**
* Highest extended PCR register
*/
u_int32_t pcr_max;
/**
* Bitmap of extended PCR registers
*/
u_int8_t pcr_select[PCR_MAX_NUM / 8];
}; };
@@ -369,12 +339,6 @@ METHOD(pts_t, set_tpm_version_info, void,
print_tpm_version_info(this); print_tpm_version_info(this);
} }
METHOD(pts_t, get_pcr_len, size_t,
private_pts_t *this)
{
return this->pcr_len;
}
/** /**
* Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute) * Load an AIK Blob (TSS_TSPATTRIB_KEYBLOB_BLOB attribute)
*/ */
@@ -715,8 +679,8 @@ METHOD(pts_t, extend_pcr, bool,
goto err; goto err;
} }
pcr_value = chunk_alloc(PCR_LEN); pcr_value = chunk_alloc(PTS_PCR_LEN);
result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr, result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr,
NULL, &pcr_length, &pcr_value.ptr); NULL, &pcr_length, &pcr_value.ptr);
if (result != TSS_SUCCESS) if (result != TSS_SUCCESS)
{ {
@@ -745,22 +709,6 @@ err:
return FALSE; return FALSE;
} }
static void clear_pcrs(private_pts_t *this)
{
int i;
for (i = 0; i <= this->pcr_max; i++)
{
free(this->pcrs[i]);
this->pcrs[i] = NULL;
}
this->pcr_count = 0;
this->pcr_max = 0;
memset(this->pcr_select, 0x00, sizeof(this->pcr_select));
}
METHOD(pts_t, quote_tpm, bool, METHOD(pts_t, quote_tpm, bool,
private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig) private_pts_t *this, bool use_quote2, chunk_t *pcr_comp, chunk_t *quote_sig)
{ {
@@ -776,7 +724,8 @@ METHOD(pts_t, quote_tpm, bool,
TSS_RESULT result; TSS_RESULT result;
chunk_t quote_info; chunk_t quote_info;
BYTE* versionInfo; BYTE* versionInfo;
u_int32_t versionInfoSize, pcr, i = 0, f = 1; u_int32_t versionInfoSize, pcr;
enumerator_t *enumerator;
bool success = FALSE; bool success = FALSE;
result = Tspi_Context_Create(&hContext); result = Tspi_Context_Create(&hContext);
@@ -836,25 +785,23 @@ METHOD(pts_t, quote_tpm, bool,
} }
/* Select PCRs */ /* Select PCRs */
for (pcr = 0; pcr <= this->pcr_max ; pcr++) enumerator = this->pcrs->create_enumerator(this->pcrs);
while (enumerator->enumerate(enumerator, &pcr))
{ {
if (f == 256) result = use_quote2 ?
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
TSS_PCRS_DIRECTION_RELEASE) :
Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
if (result != TSS_SUCCESS)
{ {
i++; break;
f = 1;
} }
if (this->pcr_select[i] & f) }
{ enumerator->destroy(enumerator);
result = use_quote2 ?
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr, if (result != TSS_SUCCESS)
TSS_PCRS_DIRECTION_RELEASE) : {
Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr); goto err3;
if (result != TSS_SUCCESS)
{
goto err3;
}
}
f <<= 1;
} }
/* Set the Validation Data */ /* Set the Validation Data */
@@ -914,87 +861,14 @@ err1:
{ {
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result); DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
} }
clear_pcrs(this);
return success; return success;
} }
METHOD(pts_t, select_pcr, bool, METHOD(pts_t, get_pcrs, pts_pcr_t*,
private_pts_t *this, u_int32_t pcr) private_pts_t *this)
{ {
u_int32_t i, f; return this->pcrs;
if (pcr >= PCR_MAX_NUM)
{
DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
pcr, PCR_MAX_NUM-1);
return FALSE;
}
/* Determine PCR selection flag */
i = pcr / 8;
f = 1 << (pcr - 8*i);
/* Has this PCR already been selected? */
if (!(this->pcr_select[i] & f))
{
this->pcr_select[i] |= f;
this->pcr_max = max(this->pcr_max, pcr);
this->pcr_count++;
}
return TRUE;
}
METHOD(pts_t, add_pcr, bool,
private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after)
{
if (pcr >= PCR_MAX_NUM)
{
DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
pcr, PCR_MAX_NUM-1);
return FALSE;
}
/* Is the length of the PCR registers already set? */
if (this->pcr_len)
{
if (pcr_after.len != this->pcr_len)
{
DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes",
pcr_after.len, this->pcr_len);
return FALSE;
}
}
else
{
this->pcr_len = pcr_after.len;
}
/* Has the value of the PCR register already been assigned? */
if (this->pcrs[pcr])
{
if (!memeq(this->pcrs[pcr], pcr_before.ptr, this->pcr_len))
{
DBG1(DBG_PTS, "PCR %02u: new pcr_before value does not equal "
"old pcr_after value");
}
/* remove the old PCR value */
free(this->pcrs[pcr]);
}
else
{
/* add extended PCR Register */
this->pcr_select[pcr / 8] |= 1 << (pcr % 8);
this->pcr_max = max(this->pcr_max, pcr);
this->pcr_count++;
}
/* Duplicate and store current PCR value */
pcr_after = chunk_clone(pcr_after);
this->pcrs[pcr] = pcr_after.ptr;
return TRUE;
} }
/** /**
@@ -1016,13 +890,11 @@ METHOD(pts_t, get_quote_info, bool,
pts_meas_algorithms_t comp_hash_algo, pts_meas_algorithms_t comp_hash_algo,
chunk_t *out_pcr_comp, chunk_t *out_quote_info) chunk_t *out_pcr_comp, chunk_t *out_quote_info)
{ {
u_int8_t size_of_select; chunk_t selection, pcr_comp, hash_pcr_comp;
int pcr_comp_len, i;
chunk_t pcr_comp, hash_pcr_comp;
bio_writer_t *writer; bio_writer_t *writer;
hasher_t *hasher; hasher_t *hasher;
if (this->pcr_count == 0) if (!this->pcrs->get_count(this->pcrs))
{ {
DBG1(DBG_PTS, "No extended PCR entries available, " DBG1(DBG_PTS, "No extended PCR entries available, "
"unable to construct TPM Quote Info"); "unable to construct TPM Quote Info");
@@ -1041,33 +913,8 @@ METHOD(pts_t, get_quote_info, bool,
return FALSE; return FALSE;
} }
/** pcr_comp = this->pcrs->get_composite(this->pcrs);
* A TPM v1.2 has 24 PCR Registers
* so the bitmask field length used by TrouSerS is at least 3 bytes
*/
size_of_select = max(PCR_MAX_NUM / 8, 1 + this->pcr_max / 8);
pcr_comp_len = 2 + size_of_select + 4 + this->pcr_count * this->pcr_len;
writer = bio_writer_create(pcr_comp_len);
writer->write_uint16(writer, size_of_select);
for (i = 0; i < size_of_select; i++)
{
writer->write_uint8(writer, this->pcr_select[i]);
}
writer->write_uint32(writer, this->pcr_count * this->pcr_len);
for (i = 0; i < 8 * size_of_select; i++)
{
if (this->pcrs[i])
{
writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len));
}
}
pcr_comp = chunk_clone(writer->get_buf(writer));
DBG3(DBG_PTS, "constructed PCR Composite: %B", &pcr_comp);
writer->destroy(writer);
/* Output the TPM_PCR_COMPOSITE expected from IMC */ /* Output the TPM_PCR_COMPOSITE expected from IMC */
if (comp_hash_algo) if (comp_hash_algo)
@@ -1117,14 +964,10 @@ METHOD(pts_t, get_quote_info, bool,
/* Secret assessment value 20 bytes (nonce) */ /* Secret assessment value 20 bytes (nonce) */
writer->write_data(writer, this->secret); writer->write_data(writer, this->secret);
/* Length of the PCR selection field */
writer->write_uint16(writer, size_of_select);
/* PCR selection */ /* PCR selection */
for (i = 0; i < size_of_select ; i++) selection.ptr = pcr_comp.ptr;
{ selection.len = 2 + this->pcrs->get_selection_size(this->pcrs);
writer->write_uint8(writer, this->pcr_select[i]); writer->write_data(writer, selection);
}
/* TPM Locality Selection */ /* TPM Locality Selection */
writer->write_uint8(writer, TPM_LOC_ZERO); writer->write_uint8(writer, TPM_LOC_ZERO);
@@ -1160,7 +1003,6 @@ METHOD(pts_t, get_quote_info, bool,
writer->destroy(writer); writer->destroy(writer);
free(pcr_comp.ptr); free(pcr_comp.ptr);
free(hash_pcr_comp.ptr); free(hash_pcr_comp.ptr);
clear_pcrs(this);
return TRUE; return TRUE;
} }
@@ -1192,7 +1034,7 @@ METHOD(pts_t, verify_quote_signature, bool,
METHOD(pts_t, destroy, void, METHOD(pts_t, destroy, void,
private_pts_t *this) private_pts_t *this)
{ {
clear_pcrs(this); DESTROY_IF(this->pcrs);
DESTROY_IF(this->aik); DESTROY_IF(this->aik);
DESTROY_IF(this->dh); DESTROY_IF(this->dh);
free(this->initiator_nonce.ptr); free(this->initiator_nonce.ptr);
@@ -1374,6 +1216,14 @@ static bool has_tpm(private_pts_t *this)
pts_t *pts_create(bool is_imc) pts_t *pts_create(bool is_imc)
{ {
private_pts_t *this; private_pts_t *this;
pts_pcr_t *pcrs;
pcrs = pts_pcr_create();
if (!pcrs)
{
DBG1(DBG_PTS, "shadow PCR set could not be created");
return NULL;
}
INIT(this, INIT(this,
.public = { .public = {
@@ -1391,7 +1241,6 @@ pts_t *pts_create(bool is_imc)
.set_platform_info = _set_platform_info, .set_platform_info = _set_platform_info,
.get_tpm_version_info = _get_tpm_version_info, .get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info, .set_tpm_version_info = _set_tpm_version_info,
.get_pcr_len = _get_pcr_len,
.get_aik = _get_aik, .get_aik = _get_aik,
.set_aik = _set_aik, .set_aik = _set_aik,
.get_aik_keyid = _get_aik_keyid, .get_aik_keyid = _get_aik_keyid,
@@ -1400,8 +1249,7 @@ pts_t *pts_create(bool is_imc)
.read_pcr = _read_pcr, .read_pcr = _read_pcr,
.extend_pcr = _extend_pcr, .extend_pcr = _extend_pcr,
.quote_tpm = _quote_tpm, .quote_tpm = _quote_tpm,
.select_pcr = _select_pcr, .get_pcrs = _get_pcrs,
.add_pcr = _add_pcr,
.get_quote_info = _get_quote_info, .get_quote_info = _get_quote_info,
.verify_quote_signature = _verify_quote_signature, .verify_quote_signature = _verify_quote_signature,
.destroy = _destroy, .destroy = _destroy,
@@ -1410,6 +1258,7 @@ pts_t *pts_create(bool is_imc)
.proto_caps = PTS_PROTO_CAPS_V, .proto_caps = PTS_PROTO_CAPS_V,
.algorithm = PTS_MEAS_ALGO_SHA256, .algorithm = PTS_MEAS_ALGO_SHA256,
.dh_hash_algorithm = PTS_MEAS_ALGO_SHA256, .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
.pcrs = pcrs,
); );
if (is_imc) if (is_imc)
@@ -1419,7 +1268,6 @@ pts_t *pts_create(bool is_imc)
if (has_tpm(this)) if (has_tpm(this))
{ {
this->has_tpm = TRUE; this->has_tpm = TRUE;
this->pcr_len = PCR_LEN;
this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D; this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
load_aik(this); load_aik(this);
load_aik_blob(this); load_aik_blob(this);
+5 -23
View File
@@ -29,6 +29,7 @@ typedef struct pts_t pts_t;
#include "pts_file_meas.h" #include "pts_file_meas.h"
#include "pts_file_meta.h" #include "pts_file_meta.h"
#include "pts_dh_group.h" #include "pts_dh_group.h"
#include "pts_pcr.h"
#include "pts_req_func_comp_evid.h" #include "pts_req_func_comp_evid.h"
#include "pts_simple_evid_final.h" #include "pts_simple_evid_final.h"
#include "components/pts_comp_func_name.h" #include "components/pts_comp_func_name.h"
@@ -189,13 +190,6 @@ struct pts_t {
*/ */
void (*set_tpm_version_info)(pts_t *this, chunk_t info); void (*set_tpm_version_info)(pts_t *this, chunk_t info);
/**
* Get the length of the TPM PCR registers
*
* @return Length of PCR registers in bytes, 0 if undefined
*/
size_t (*get_pcr_len)(pts_t *this);
/** /**
* Get Attestation Identity Certificate or Public Key * Get Attestation Identity Certificate or Public Key
* *
@@ -273,24 +267,12 @@ struct pts_t {
bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp, bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
chunk_t *quote_sig); chunk_t *quote_sig);
/** /**
* Mark an extended PCR as selected * Get the shadow PCR set
* *
* @param pcr Number of the extended PCR * @return shadow PCR set
* @return TRUE if PCR number is valid
*/ */
bool (*select_pcr)(pts_t *this, u_int32_t pcr); pts_pcr_t* (*get_pcrs)(pts_t *this);
/**
* Add an extended PCR with its corresponding value
*
* @param pcr Number of the extended PCR
* @param pcr_before PCR value before extension
* @param pcr_after PCR value after extension
* @return TRUE if PCR number and register length is valid
*/
bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before,
chunk_t pcr_after);
/** /**
* Constructs and returns TPM Quote Info structure expected from IMC * Constructs and returns TPM Quote Info structure expected from IMC
+175 -21
View File
@@ -17,15 +17,7 @@
#include <debug.h> #include <debug.h>
/** #include <stdarg.h>
* Maximum number of PCR's of TPM, TPM Spec 1.2
*/
#define PCR_MAX_NUM 24
/**
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
*/
#define PCR_LEN 20
typedef struct private_pts_pcr_t private_pts_pcr_t; typedef struct private_pts_pcr_t private_pts_pcr_t;
@@ -43,7 +35,22 @@ struct private_pts_pcr_t {
/** /**
* Shadow PCR registers * Shadow PCR registers
*/ */
chunk_t pcrs[PCR_MAX_NUM]; chunk_t pcrs[PTS_PCR_MAX_NUM];
/**
* Number of extended PCR registers
*/
u_int32_t pcr_count;
/**
* Highest extended PCR register
*/
u_int32_t pcr_max;
/**
* Bitmap of extended PCR registers
*/
u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8];
/** /**
* Hasher used to extend shadow PCRs * Hasher used to extend shadow PCRs
@@ -52,44 +59,186 @@ struct private_pts_pcr_t {
}; };
METHOD(pts_pcr_t, get_count, u_int32_t,
private_pts_pcr_t *this)
{
return this->pcr_count;
}
METHOD(pts_pcr_t, select_pcr, bool,
private_pts_pcr_t *this, u_int32_t pcr)
{
u_int32_t i, f;
if (pcr >= PTS_PCR_MAX_NUM)
{
DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
pcr, PTS_PCR_MAX_NUM-1);
return FALSE;
}
/* Determine PCR selection flag */
i = pcr / 8;
f = 1 << (pcr - 8*i);
/* Has this PCR already been selected? */
if (!(this->pcr_select[i] & f))
{
this->pcr_select[i] |= f;
this->pcr_max = max(this->pcr_max, pcr);
this->pcr_count++;
}
return TRUE;
}
METHOD(pts_pcr_t, get_selection_size, size_t,
private_pts_pcr_t *this)
{
/**
* A TPM v1.2 has 24 PCR Registers so the bitmask field length
* used by TrouSerS is at least 3 bytes
*/
return PTS_PCR_MAX_NUM / 8;
}
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** current PCR */
u_int32_t pcr;
/** back reference to parent */
private_pts_pcr_t *pcrs;
} pcr_enumerator_t;
/**
* Implementation of enumerator.enumerate
*/
static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
{
u_int32_t *pcr, i, f;
va_list args;
va_start(args, this);
pcr = va_arg(args, u_int32_t*);
va_end(args);
while (this->pcr <= this->pcrs->pcr_max)
{
/* Determine PCR selection flag */
i = this->pcr / 8;
f = 1 << (this->pcr - 8*i);
/* Assign current PCR to output argument and increase */
*pcr = this->pcr++;
/* return if PCR is selected */
if (this->pcrs->pcr_select[i] & f)
{
return TRUE;
}
}
return FALSE;
}
METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
private_pts_pcr_t *this)
{
pcr_enumerator_t *enumerator;
INIT(enumerator,
.public = {
.enumerate = (void*)pcr_enumerator_enumerate,
.destroy = (void*)free,
},
.pcrs = this,
);
return (enumerator_t*)enumerator;
}
METHOD(pts_pcr_t, get, chunk_t, METHOD(pts_pcr_t, get, chunk_t,
private_pts_pcr_t *this, u_int32_t pcr) private_pts_pcr_t *this, u_int32_t pcr)
{ {
return (pcr < PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty; return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
} }
METHOD(pts_pcr_t, set, void, METHOD(pts_pcr_t, set, bool,
private_pts_pcr_t *this, u_int32_t pcr, chunk_t value) private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
{ {
if (pcr < PCR_MAX_NUM && value.len == PCR_LEN) if (value.len != PTS_PCR_LEN)
{ {
memcpy(this->pcrs[pcr].ptr, value.ptr, PCR_LEN); DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
return FALSE;
} }
if (select_pcr(this, pcr))
{
memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
return TRUE;
}
return FALSE;
} }
METHOD(pts_pcr_t, extend, chunk_t, METHOD(pts_pcr_t, extend, chunk_t,
private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement) private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
{ {
if (pcr >= PCR_MAX_NUM || measurement.len != PCR_LEN) if (measurement.len != PTS_PCR_LEN)
{
DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
return chunk_empty;
}
if (!select_pcr(this, pcr))
{ {
DBG1(DBG_PTS, "PCR%d does not exist or has the wrong size", pcr);
return chunk_empty; return chunk_empty;
} }
if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) || if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
!this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr)) !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
{ {
DBG1(DBG_PTS, "PCR%d was not extended due to a hasher problem", pcr); DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
return chunk_empty; return chunk_empty;
} }
return this->pcrs[pcr]; return this->pcrs[pcr];
} }
METHOD(pts_pcr_t, get_composite, chunk_t,
private_pts_pcr_t *this)
{
chunk_t composite;
enumerator_t *enumerator;
u_int16_t selection_size;
u_int32_t pcr_field_size, pcr;
u_char *pos;
selection_size = get_selection_size(this);
pcr_field_size = this->pcr_count * PTS_PCR_LEN;
composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
pos = composite.ptr;
htoun16(pos, selection_size);
pos += 2;
memcpy(pos, this->pcr_select, selection_size);
pos += selection_size;
htoun32(pos, pcr_field_size);
pos += 4;
enumerator = create_enumerator(this);
while (enumerator->enumerate(enumerator, &pcr))
{
memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
pos += PTS_PCR_LEN;
}
enumerator->destroy(enumerator);
DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
return composite;
}
METHOD(pts_pcr_t, destroy, void, METHOD(pts_pcr_t, destroy, void,
private_pts_pcr_t *this) private_pts_pcr_t *this)
{ {
u_int32_t i; u_int32_t i;
for (i = 0; i < PCR_MAX_NUM; i++) for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{ {
free(this->pcrs[i].ptr); free(this->pcrs[i].ptr);
} }
@@ -116,18 +265,23 @@ pts_pcr_t *pts_pcr_create(void)
INIT(this, INIT(this,
.public = { .public = {
.get_count = _get_count,
.select_pcr = _select_pcr,
.get_selection_size = _get_selection_size,
.create_enumerator = _create_enumerator,
.get = _get, .get = _get,
.set = _set, .set = _set,
.extend = _extend, .extend = _extend,
.get_composite = _get_composite,
.destroy = _destroy, .destroy = _destroy,
}, },
.hasher = hasher, .hasher = hasher,
); );
for (i = 0; i < PCR_MAX_NUM; i++) for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{ {
this->pcrs[i] = chunk_alloc(PCR_LEN); this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
memset(this->pcrs[i].ptr, 0x00, PCR_LEN); memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
} }
return &this->public; return &this->public;
+49 -1
View File
@@ -25,11 +25,50 @@ typedef struct pts_pcr_t pts_pcr_t;
#include <library.h> #include <library.h>
/**
* Maximum number of PCR's of TPM, TPM Spec 1.2
*/
#define PTS_PCR_MAX_NUM 24
/**
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
*/
#define PTS_PCR_LEN 20
/** /**
* Class implementing a shadow PCR register set * Class implementing a shadow PCR register set
*/ */
struct pts_pcr_t { struct pts_pcr_t {
/**
* Get the number of selected PCRs
*
* @return number of selected PCRs
*/
u_int32_t (*get_count)(pts_pcr_t *this);
/**
* Mark a PCR as selected
*
* @param pcr index of PCR
* @return TRUE if PCR index exists
*/
bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
/**
* Get the size of the selection field in bytes
*
* @return number of bytes written
*/
size_t (*get_selection_size)(pts_pcr_t *this);
/**
* Create an enumerator over all selected PCR indexes
*
* @return enumerator
*/
enumerator_t* (*create_enumerator)(pts_pcr_t *this);
/** /**
* Get the current content of a PCR * Get the current content of a PCR
* *
@@ -43,8 +82,9 @@ struct pts_pcr_t {
* *
* @param pcr index of PCR * @param pcr index of PCR
* @param value new value of PCR * @param value new value of PCR
* @return TRUE if value could be set
*/ */
void (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value); bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
/** /**
* Extend the content of a PCR * Extend the content of a PCR
@@ -56,6 +96,14 @@ struct pts_pcr_t {
chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement); chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
/** /**
* Create a PCR Composite object over all selected PCRs
*
* @return PCR Composite object (must be freed)
*/
chunk_t (*get_composite)(pts_pcr_t *this);
/**
* Destroys a pts_pcr_t object. * Destroys a pts_pcr_t object.
*/ */
void (*destroy)(pts_pcr_t *this); void (*destroy)(pts_pcr_t *this);