aboutsummaryrefslogtreecommitdiffstats
path: root/src/libpts
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2012-07-21 15:56:39 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2012-07-21 15:58:13 +0200
commit4c020862411c1f52154ea5a98507cdfbc5a88e6b (patch)
tree6818c3e816df42a2af2658b6724f645c360bd3f9 /src/libpts
parent3b7468b245f2888be57bbf5531b0191b968e2da1 (diff)
downloadstrongswan-4c020862411c1f52154ea5a98507cdfbc5a88e6b.tar.bz2
strongswan-4c020862411c1f52154ea5a98507cdfbc5a88e6b.tar.xz
moved all shadow PCR stuff to the pts_pcr class
Diffstat (limited to 'src/libpts')
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation_process.c3
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c61
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c32
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c23
-rw-r--r--src/libpts/pts/pts.c234
-rw-r--r--src/libpts/pts/pts.h28
-rw-r--r--src/libpts/pts/pts_pcr.c196
-rw-r--r--src/libpts/pts/pts_pcr.h50
8 files changed, 335 insertions, 292 deletions
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_process.c b/src/libpts/plugins/imc_attestation/imc_attestation_process.c
index edaaa570f..5ba9f8790 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation_process.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation_process.c
@@ -420,9 +420,6 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
/* Send buffered Simple Component Evidences */
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_list->insert_last(attr_list, attr);
}
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index b687c0f8e..d57fe6a9d 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -122,11 +122,6 @@ struct pts_ita_comp_ima_t {
linked_list_t *ima_list;
/**
- * Shadow PCR set
- */
- pts_pcr_t *pcrs;
-
- /**
* Whether to send pcr_before and pcr_after info
*/
bool pcr_info;
@@ -361,8 +356,8 @@ static bool load_runtime_measurements(char *file, linked_list_t *list,
/**
* Extend measurement into PCR an create evidence
*/
-static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, u_int32_t pcr,
- chunk_t measurement)
+static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this, pts_pcr_t *pcrs,
+ u_int32_t pcr, chunk_t measurement)
{
size_t pcr_len;
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)
{
- 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)
{
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);
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);
}
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
*/
-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_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++)
{
- 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)
{
@@ -468,8 +463,10 @@ METHOD(pts_component_t, measure, status_t,
status_t status;
int count;
enumerator_t *e;
+ pts_pcr_t *pcrs;
pts_file_meas_t *file_meas;
+ pcrs = pts->get_pcrs(pts);
*measurements = NULL;
switch (this->state)
@@ -490,8 +487,8 @@ METHOD(pts_component_t, measure, status_t,
DBG1(DBG_PTS, "could not retrieve bios measurement entry");
return status;
}
- *evidence = extend_pcr(this, bios_entry->pcr,
- bios_entry->measurement);
+ *evidence = extend_pcr(this, pcrs, bios_entry->pcr,
+ bios_entry->measurement);
free(bios_entry);
if (!evidence)
{
@@ -545,11 +542,11 @@ METHOD(pts_component_t, measure, status_t,
DBG1(DBG_PTS, "could not retrieve ima measurement entry");
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)
{
- check_boot_aggregate(this, ima_entry->measurement);
+ check_boot_aggregate(pcrs, ima_entry->measurement);
}
free(ima_entry->file_measurement.ptr);
@@ -578,10 +575,12 @@ METHOD(pts_component_t, verify, status_t,
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;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&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);
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)))
+ {
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value",
+ extended_pcr);
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
{
- return FAILED;
+ return SUCCESS;
}
}
-
- return SUCCESS;
+ else
+ {
+ pcr_after = pcrs->extend(pcrs, extended_pcr, measurement);
+ if (pcr_after.ptr)
+ {
+ return SUCCESS;
+ }
+ }
+ return FAILED;
}
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->ima_list->destroy_function(this->ima_list, (void *)free_ima_entry);
this->name->destroy(this->name);
- this->pcrs->destroy(this->pcrs);
free(this->keyid.ptr);
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_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,
.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(),
.ima_list = linked_list_create(),
.ima_count = IMA_MEASUREMENT_BATCH_SIZE - 1,
- .pcrs = pcrs,
.pcr_info = lib->settings->get_bool(lib->settings,
"libimcv.plugins.imc-attestation.pcr_info", TRUE),
);
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index 8ac8335bf..40befc3e0 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -110,13 +110,14 @@ METHOD(pts_component_t, measure, status_t,
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;
char *meas_hex, *pcr_before_hex, *pcr_after_hex;
chunk_t measurement, pcr_before, pcr_after;
- size_t hash_size, pcr_len;
u_int32_t extended_pcr;
- pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
switch (this->seq_no++)
{
@@ -150,9 +151,8 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
/* get and check the measurement data */
@@ -163,7 +163,7 @@ METHOD(pts_component_t, measure, status_t,
pcr_after = chunk_from_hex(
chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
- measurement.len != hash_size)
+ measurement.len != pcr_len)
{
DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
free(measurement.ptr);
@@ -172,10 +172,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
+ pcrs = pts->get_pcrs(pts);
+ pcrs->set(pcrs, extended_pcr, pcr_after);
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
- this->depth, extended_pcr,
- hash_algo, pcr_transform,
- this->measurement_time, measurement);
+ this->depth, extended_pcr, hash_algo, pcr_transform,
+ this->measurement_time, measurement);
evid->set_pcr_info(evid, pcr_before, pcr_after);
return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
@@ -189,10 +190,12 @@ METHOD(pts_component_t, verify, status_t,
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;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&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);
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;
}
}
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c
index a25f2f8ab..1d24b0a93 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -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_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;
u_int32_t extended_pcr;
time_t measurement_time;
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 */
extended_pcr = PCR_DEBUG;
@@ -91,12 +91,11 @@ METHOD(pts_component_t, measure, status_t,
return FAILED;
}
- hash_algo = pts->get_meas_algorithm(pts);
- hash_size = pts_meas_algo_hash_size(hash_algo);
- pcr_len = pts->get_pcr_len(pts);
+ hash_algo = PTS_MEAS_ALGO_SHA1;
+ pcr_len = HASH_SIZE_SHA1;
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
- measurement = chunk_alloc(hash_size);
+ measurement = chunk_alloc(pcr_len);
memset(measurement.ptr, 0x00, measurement.len);
pcr_before = chunk_alloc(pcr_len);
@@ -118,9 +117,11 @@ METHOD(pts_component_t, verify, status_t,
u_int32_t extended_pcr;
pts_meas_algorithms_t algo;
pts_pcr_transform_t transform;
+ pts_pcr_t *pcrs;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
+ pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
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);
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)))
+ {
+ DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
+ }
+ if (pcrs->set(pcrs, extended_pcr, pcr_after))
{
- return FAILED;
+ return SUCCESS;
}
}
diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c
index 16047aa08..769890fa3 100644
--- a/src/libpts/pts/pts.c
+++ b/src/libpts/pts/pts.c
@@ -30,16 +30,6 @@
#include <unistd.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;
/**
@@ -119,29 +109,9 @@ struct private_pts_t {
certificate_t *aik;
/**
- * Table of extended PCRs with corresponding values
- */
- u_char* pcrs[PCR_MAX_NUM];
-
- /**
- * Length of PCR registers
- */
- size_t pcr_len;
-
- /**
- * Number of extended PCR registers
+ * Shadow PCR set
*/
- 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];
+ pts_pcr_t *pcrs;
};
@@ -369,12 +339,6 @@ METHOD(pts_t, set_tpm_version_info, void,
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)
*/
@@ -715,8 +679,8 @@ METHOD(pts_t, extend_pcr, bool,
goto err;
}
- pcr_value = chunk_alloc(PCR_LEN);
- result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr,
+ pcr_value = chunk_alloc(PTS_PCR_LEN);
+ result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PTS_PCR_LEN, input.ptr,
NULL, &pcr_length, &pcr_value.ptr);
if (result != TSS_SUCCESS)
{
@@ -745,22 +709,6 @@ err:
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,
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;
chunk_t quote_info;
BYTE* versionInfo;
- u_int32_t versionInfoSize, pcr, i = 0, f = 1;
+ u_int32_t versionInfoSize, pcr;
+ enumerator_t *enumerator;
bool success = FALSE;
result = Tspi_Context_Create(&hContext);
@@ -836,25 +785,23 @@ METHOD(pts_t, quote_tpm, bool,
}
/* Select PCRs */
- for (pcr = 0; pcr <= this->pcr_max ; pcr++)
- {
- if (f == 256)
- {
- i++;
- f = 1;
- }
- if (this->pcr_select[i] & f)
+ enumerator = this->pcrs->create_enumerator(this->pcrs);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ result = use_quote2 ?
+ Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
+ TSS_PCRS_DIRECTION_RELEASE) :
+ Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
+ if (result != TSS_SUCCESS)
{
- result = use_quote2 ?
- Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
- TSS_PCRS_DIRECTION_RELEASE) :
- Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
- if (result != TSS_SUCCESS)
- {
- goto err3;
- }
+ break;
}
- f <<= 1;
+ }
+ enumerator->destroy(enumerator);
+
+ if (result != TSS_SUCCESS)
+ {
+ goto err3;
}
/* Set the Validation Data */
@@ -914,87 +861,14 @@ err1:
{
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
}
- clear_pcrs(this);
return success;
}
-METHOD(pts_t, select_pcr, bool,
- private_pts_t *this, u_int32_t pcr)
-{
- u_int32_t i, f;
-
- 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)
+METHOD(pts_t, get_pcrs, pts_pcr_t*,
+ private_pts_t *this)
{
- 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;
+ return this->pcrs;
}
/**
@@ -1016,13 +890,11 @@ METHOD(pts_t, get_quote_info, bool,
pts_meas_algorithms_t comp_hash_algo,
chunk_t *out_pcr_comp, chunk_t *out_quote_info)
{
- u_int8_t size_of_select;
- int pcr_comp_len, i;
- chunk_t pcr_comp, hash_pcr_comp;
+ chunk_t selection, pcr_comp, hash_pcr_comp;
bio_writer_t *writer;
hasher_t *hasher;
- if (this->pcr_count == 0)
+ if (!this->pcrs->get_count(this->pcrs))
{
DBG1(DBG_PTS, "No extended PCR entries available, "
"unable to construct TPM Quote Info");
@@ -1041,33 +913,8 @@ METHOD(pts_t, get_quote_info, bool,
return FALSE;
}
- /**
- * 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);
+ pcr_comp = this->pcrs->get_composite(this->pcrs);
- 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 */
if (comp_hash_algo)
@@ -1117,14 +964,10 @@ METHOD(pts_t, get_quote_info, bool,
/* Secret assessment value 20 bytes (nonce) */
writer->write_data(writer, this->secret);
- /* Length of the PCR selection field */
- writer->write_uint16(writer, size_of_select);
-
/* PCR selection */
- for (i = 0; i < size_of_select ; i++)
- {
- writer->write_uint8(writer, this->pcr_select[i]);
- }
+ selection.ptr = pcr_comp.ptr;
+ selection.len = 2 + this->pcrs->get_selection_size(this->pcrs);
+ writer->write_data(writer, selection);
/* TPM Locality Selection */
writer->write_uint8(writer, TPM_LOC_ZERO);
@@ -1160,7 +1003,6 @@ METHOD(pts_t, get_quote_info, bool,
writer->destroy(writer);
free(pcr_comp.ptr);
free(hash_pcr_comp.ptr);
- clear_pcrs(this);
return TRUE;
}
@@ -1192,7 +1034,7 @@ METHOD(pts_t, verify_quote_signature, bool,
METHOD(pts_t, destroy, void,
private_pts_t *this)
{
- clear_pcrs(this);
+ DESTROY_IF(this->pcrs);
DESTROY_IF(this->aik);
DESTROY_IF(this->dh);
free(this->initiator_nonce.ptr);
@@ -1374,6 +1216,14 @@ static bool has_tpm(private_pts_t *this)
pts_t *pts_create(bool is_imc)
{
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,
.public = {
@@ -1391,7 +1241,6 @@ pts_t *pts_create(bool is_imc)
.set_platform_info = _set_platform_info,
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
- .get_pcr_len = _get_pcr_len,
.get_aik = _get_aik,
.set_aik = _set_aik,
.get_aik_keyid = _get_aik_keyid,
@@ -1400,8 +1249,7 @@ pts_t *pts_create(bool is_imc)
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote_tpm = _quote_tpm,
- .select_pcr = _select_pcr,
- .add_pcr = _add_pcr,
+ .get_pcrs = _get_pcrs,
.get_quote_info = _get_quote_info,
.verify_quote_signature = _verify_quote_signature,
.destroy = _destroy,
@@ -1410,6 +1258,7 @@ pts_t *pts_create(bool is_imc)
.proto_caps = PTS_PROTO_CAPS_V,
.algorithm = PTS_MEAS_ALGO_SHA256,
.dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+ .pcrs = pcrs,
);
if (is_imc)
@@ -1419,7 +1268,6 @@ pts_t *pts_create(bool is_imc)
if (has_tpm(this))
{
this->has_tpm = TRUE;
- this->pcr_len = PCR_LEN;
this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
load_aik(this);
load_aik_blob(this);
diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h
index c35f68687..5f88cd15c 100644
--- a/src/libpts/pts/pts.h
+++ b/src/libpts/pts/pts.h
@@ -29,6 +29,7 @@ typedef struct pts_t pts_t;
#include "pts_file_meas.h"
#include "pts_file_meta.h"
#include "pts_dh_group.h"
+#include "pts_pcr.h"
#include "pts_req_func_comp_evid.h"
#include "pts_simple_evid_final.h"
#include "components/pts_comp_func_name.h"
@@ -190,13 +191,6 @@ struct pts_t {
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
*
* @return AIK Certificate or Public Key
@@ -273,24 +267,12 @@ struct pts_t {
bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
chunk_t *quote_sig);
- /**
- * Mark an extended PCR as selected
- *
- * @param pcr Number of the extended PCR
- * @return TRUE if PCR number is valid
- */
- bool (*select_pcr)(pts_t *this, u_int32_t pcr);
-
- /**
- * Add an extended PCR with its corresponding value
+ /**
+ * Get the shadow PCR set
*
- * @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
+ * @return shadow PCR set
*/
- bool (*add_pcr)(pts_t *this, u_int32_t pcr, chunk_t pcr_before,
- chunk_t pcr_after);
+ pts_pcr_t* (*get_pcrs)(pts_t *this);
/**
* Constructs and returns TPM Quote Info structure expected from IMC
diff --git a/src/libpts/pts/pts_pcr.c b/src/libpts/pts/pts_pcr.c
index c21e585e7..a7a2f5fae 100644
--- a/src/libpts/pts/pts_pcr.c
+++ b/src/libpts/pts/pts_pcr.c
@@ -17,15 +17,7 @@
#include <debug.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
+#include <stdarg.h>
typedef struct private_pts_pcr_t private_pts_pcr_t;
@@ -43,7 +35,22 @@ struct private_pts_pcr_t {
/**
* 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
@@ -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,
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)
{
- if (pcr < PCR_MAX_NUM && value.len == PCR_LEN)
+ if (value.len != PTS_PCR_LEN)
+ {
+ DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
+ return FALSE;
+ }
+ if (select_pcr(this, pcr))
{
- memcpy(this->pcrs[pcr].ptr, value.ptr, PCR_LEN);
+ memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
+ return TRUE;
}
+ return FALSE;
}
METHOD(pts_pcr_t, extend, chunk_t,
private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
{
- if (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;
}
if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
!this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
{
- DBG1(DBG_PTS, "PCR%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 this->pcrs[pcr];
}
+METHOD(pts_pcr_t, get_composite, chunk_t,
+ private_pts_pcr_t *this)
+{
+ chunk_t composite;
+ enumerator_t *enumerator;
+ u_int16_t selection_size;
+ u_int32_t pcr_field_size, pcr;
+ u_char *pos;
+
+ selection_size = get_selection_size(this);
+ pcr_field_size = this->pcr_count * PTS_PCR_LEN;
+
+ composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
+ pos = composite.ptr;
+ htoun16(pos, selection_size);
+ pos += 2;
+ memcpy(pos, this->pcr_select, selection_size);
+ pos += selection_size;
+ htoun32(pos, pcr_field_size);
+ pos += 4;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &pcr))
+ {
+ memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
+ pos += PTS_PCR_LEN;
+ }
+ enumerator->destroy(enumerator);
+
+ DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
+ return composite;
+}
+
METHOD(pts_pcr_t, destroy, void,
private_pts_pcr_t *this)
{
u_int32_t i;
- for (i = 0; i < PCR_MAX_NUM; i++)
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{
free(this->pcrs[i].ptr);
}
@@ -116,18 +265,23 @@ pts_pcr_t *pts_pcr_create(void)
INIT(this,
.public = {
+ .get_count = _get_count,
+ .select_pcr = _select_pcr,
+ .get_selection_size = _get_selection_size,
+ .create_enumerator = _create_enumerator,
.get = _get,
.set = _set,
.extend = _extend,
+ .get_composite = _get_composite,
.destroy = _destroy,
},
.hasher = hasher,
);
- for (i = 0; i < PCR_MAX_NUM; i++)
+ for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{
- this->pcrs[i] = chunk_alloc(PCR_LEN);
- memset(this->pcrs[i].ptr, 0x00, PCR_LEN);
+ this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
+ memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
}
return &this->public;
diff --git a/src/libpts/pts/pts_pcr.h b/src/libpts/pts/pts_pcr.h
index 43a85dbe9..f638b5ee4 100644
--- a/src/libpts/pts/pts_pcr.h
+++ b/src/libpts/pts/pts_pcr.h
@@ -26,11 +26,50 @@ typedef struct pts_pcr_t pts_pcr_t;
#include <library.h>
/**
+ * Maximum number of PCR's of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_MAX_NUM 24
+
+/**
+ * Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
+ */
+#define PTS_PCR_LEN 20
+
+/**
* Class implementing a shadow PCR register set
*/
struct pts_pcr_t {
/**
+ * Get the number of selected PCRs
+ *
+ * @return number of selected PCRs
+ */
+ u_int32_t (*get_count)(pts_pcr_t *this);
+
+ /**
+ * Mark a PCR as selected
+ *
+ * @param pcr index of PCR
+ * @return TRUE if PCR index exists
+ */
+ bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
+
+ /**
+ * Get the size of the selection field in bytes
+ *
+ * @return number of bytes written
+ */
+ size_t (*get_selection_size)(pts_pcr_t *this);
+
+ /**
+ * Create an enumerator over all selected PCR indexes
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_enumerator)(pts_pcr_t *this);
+
+ /**
* Get the current content of a PCR
*
* @param pcr index of PCR
@@ -43,8 +82,9 @@ struct pts_pcr_t {
*
* @param pcr index 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
@@ -56,6 +96,14 @@ struct pts_pcr_t {
chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
/**
+ * Create a PCR Composite object over all selected PCRs
+ *
+ * @return PCR Composite object (must be freed)
+ */
+ chunk_t (*get_composite)(pts_pcr_t *this);
+
+ /**
+
* Destroys a pts_pcr_t object.
*/
void (*destroy)(pts_pcr_t *this);