moved all shadow PCR stuff to the pts_pcr class
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user