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 */
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);
}
+31 -30
View File
@@ -121,11 +121,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
*/
@@ -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)))
{
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;
}
}
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),
);
+20 -12
View File
@@ -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;
}
}
+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_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)))
{
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 <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
* Shadow PCR set
*/
u_char* pcrs[PCR_MAX_NUM];
/**
* 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];
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++)
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++;
f = 1;
break;
}
if (this->pcr_select[i] & f)
{
result = use_quote2 ?
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
TSS_PCRS_DIRECTION_RELEASE) :
Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr);
if (result != TSS_SUCCESS)
{
goto err3;
}
}
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)
METHOD(pts_t, get_pcrs, pts_pcr_t*,
private_pts_t *this)
{
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)
{
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;
pcr_comp = this->pcrs->get_composite(this->pcrs);
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 */
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);
+5 -23
View File
@@ -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"
@@ -189,13 +190,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
*
@@ -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
/**
* Get the shadow PCR set
*
* @param pcr Number of the extended PCR
* @return TRUE if PCR number is valid
* @return shadow PCR set
*/
bool (*select_pcr)(pts_t *this, u_int32_t pcr);
/**
* 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);
pts_pcr_t* (*get_pcrs)(pts_t *this);
/**
* Constructs and returns TPM Quote Info structure expected from IMC
+175 -21
View File
@@ -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)
{
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,
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;
+49 -1
View File
@@ -25,11 +25,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
*
@@ -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);