refactored PCR functionality
This commit is contained in:
@@ -406,39 +406,25 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
{
|
{
|
||||||
pts_simple_evid_final_flag_t flags;
|
pts_simple_evid_final_flag_t flags;
|
||||||
pts_meas_algorithms_t composite_algorithm = 0;
|
pts_meas_algorithms_t composite_algorithm = 0;
|
||||||
pts_comp_evidence_t *evidence;
|
pts_comp_evidence_t *evid;
|
||||||
chunk_t pcr_composite, quote_signature;
|
chunk_t pcr_composite, quote_signature;
|
||||||
u_int32_t i, evid_count, extended_pcr;
|
|
||||||
u_int32_t *pcrs;
|
|
||||||
bool use_quote2;
|
bool use_quote2;
|
||||||
|
|
||||||
/* Send buffered Simple Component Evidences */
|
/* Send buffered Simple Component Evidences */
|
||||||
evid_count = attestation_state->get_evid_count(attestation_state);
|
while (attestation_state->next_evidence(attestation_state, &evid))
|
||||||
pcrs = (u_int32_t*)malloc(sizeof(u_int32_t)*evid_count);
|
|
||||||
|
|
||||||
for (i = 0; i < evid_count; i++)
|
|
||||||
{
|
{
|
||||||
evidence = attestation_state->next_evidence(attestation_state);
|
pts->select_pcr(pts, evid->get_extended_pcr(evid));
|
||||||
extended_pcr = evidence->get_extended_pcr(evidence);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add extended PCR number to PCR list to quote
|
|
||||||
* Duplicated PCR numbers have no influence
|
|
||||||
*/
|
|
||||||
pcrs[i] = extended_pcr;
|
|
||||||
|
|
||||||
/* Send Simple Component Evidence */
|
/* Send Simple Component Evidence */
|
||||||
attr = tcg_pts_attr_simple_comp_evid_create(evidence);
|
attr = tcg_pts_attr_simple_comp_evid_create(evid);
|
||||||
attr_list->insert_last(attr_list, attr);
|
attr_list->insert_last(attr_list, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
use_quote2 = (lib->settings->get_int(lib->settings,
|
use_quote2 = lib->settings->get_bool(lib->settings,
|
||||||
"libimcv.plugins.imc-attestation.quote_version", 1) == 1) ?
|
"libimcv.plugins.imc-attestation.use_quote2", TRUE);
|
||||||
FALSE : TRUE;
|
|
||||||
|
|
||||||
/* Quote */
|
/* Quote */
|
||||||
if (!pts->quote_tpm(pts, use_quote2, pcrs, evid_count,
|
if (!pts->quote_tpm(pts, use_quote2, &pcr_composite, "e_signature))
|
||||||
&pcr_composite, "e_signature))
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMC, "error occured during TPM quote operation");
|
DBG1(DBG_IMC, "error occured during TPM quote operation");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -85,26 +85,12 @@ METHOD(imc_attestation_state_t, add_evidence, void,
|
|||||||
this->list->insert_last(this->list, evidence);
|
this->list->insert_last(this->list, evidence);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(imc_attestation_state_t, get_evid_count, int,
|
METHOD(imc_attestation_state_t, next_evidence, bool,
|
||||||
private_imc_attestation_state_t *this)
|
private_imc_attestation_state_t *this, pts_comp_evidence_t **evid)
|
||||||
{
|
{
|
||||||
return this->list->get_count(this->list);
|
return this->list->remove_first(this->list, (void**)evid) == SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(imc_attestation_state_t, next_evidence, pts_comp_evidence_t*,
|
|
||||||
private_imc_attestation_state_t *this)
|
|
||||||
{
|
|
||||||
pts_comp_evidence_t *evidence;
|
|
||||||
|
|
||||||
if (this->list->remove_first(this->list, (void**)&evidence) == SUCCESS)
|
|
||||||
{
|
|
||||||
return evidence;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
@@ -122,7 +108,6 @@ imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id)
|
|||||||
},
|
},
|
||||||
.get_pts = _get_pts,
|
.get_pts = _get_pts,
|
||||||
.add_evidence = _add_evidence,
|
.add_evidence = _add_evidence,
|
||||||
.get_evid_count = _get_evid_count,
|
|
||||||
.next_evidence = _next_evidence,
|
.next_evidence = _next_evidence,
|
||||||
},
|
},
|
||||||
.connection_id = connection_id,
|
.connection_id = connection_id,
|
||||||
|
|||||||
@@ -53,19 +53,13 @@ struct imc_attestation_state_t {
|
|||||||
*/
|
*/
|
||||||
void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *entry);
|
void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *entry);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of entries in the Component Evidence list
|
|
||||||
*
|
|
||||||
* @return number of Component Evidence entries
|
|
||||||
*/
|
|
||||||
int (*get_evid_count)(imc_attestation_state_t *this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes next Component Evidence entry from list and returns it
|
* Removes next Component Evidence entry from list and returns it
|
||||||
*
|
*
|
||||||
* @return Next Component Evidence entry
|
* @param evid Next Component Evidence entry
|
||||||
|
* @return TRUE if next entry is available
|
||||||
*/
|
*/
|
||||||
pts_comp_evidence_t* (*next_evidence)(imc_attestation_state_t *this);
|
bool (*next_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t** evid);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
chunk_t tpm_quote_sign;
|
chunk_t tpm_quote_sign;
|
||||||
chunk_t evid_sign;
|
chunk_t evid_sign;
|
||||||
bool evid_signature_included = FALSE, use_quote2 = FALSE,
|
bool evid_signature_included = FALSE, use_quote2 = FALSE,
|
||||||
ver_info_included = FALSE;
|
ver_info_included = FALSE;
|
||||||
chunk_t pcr_composite, quote_info;
|
chunk_t pcr_composite, quote_info;
|
||||||
|
|
||||||
attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
|
attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
|
||||||
@@ -348,11 +348,10 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check calculated PCR composite matches with received */
|
|
||||||
if (!chunk_equals(pcr_comp, pcr_composite))
|
if (!chunk_equals(pcr_comp, pcr_composite))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMV, "received PCR Compsosite didn't match"
|
DBG1(DBG_IMV, "received PCR Composite didn't match "
|
||||||
" with constructed");
|
"with constructed");
|
||||||
chunk_clear(&pcr_composite);
|
chunk_clear(&pcr_composite);
|
||||||
chunk_clear("e_info);
|
chunk_clear("e_info);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
pts_pcr_transform_t transform;
|
pts_pcr_transform_t transform;
|
||||||
time_t measurement_time;
|
time_t measurement_time;
|
||||||
chunk_t measurement, pcr_before, pcr_after;
|
chunk_t measurement, pcr_before, pcr_after;
|
||||||
pcr_entry_t *entry;
|
|
||||||
|
|
||||||
switch (this->extended_pcr)
|
switch (this->extended_pcr)
|
||||||
{
|
{
|
||||||
@@ -150,10 +149,10 @@ 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)
|
||||||
{
|
{
|
||||||
entry = malloc_thing(pcr_entry_t);
|
if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
|
||||||
entry->pcr_number = extended_pcr;
|
{
|
||||||
memcpy(entry->pcr_value, pcr_after.ptr, PCR_LEN);
|
return FAILED;
|
||||||
pts->add_pcr_entry(pts, entry);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this->extended_pcr == PCR_TBOOT_MLE) ? SUCCESS : NEED_MORE;
|
return (this->extended_pcr == PCR_TBOOT_MLE) ? SUCCESS : NEED_MORE;
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
pts_pcr_transform_t transform;
|
pts_pcr_transform_t transform;
|
||||||
time_t measurement_time;
|
time_t measurement_time;
|
||||||
chunk_t measurement, pcr_before, pcr_after;
|
chunk_t measurement, pcr_before, pcr_after;
|
||||||
pcr_entry_t *entry;
|
|
||||||
|
|
||||||
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
||||||
&algo, &transform, &measurement_time);
|
&algo, &transform, &measurement_time);
|
||||||
@@ -110,10 +109,10 @@ 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)
|
||||||
{
|
{
|
||||||
entry = malloc_thing(pcr_entry_t);
|
if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
|
||||||
entry->pcr_number = extended_pcr;
|
{
|
||||||
memcpy(entry->pcr_value, pcr_after.ptr, PCR_LEN);
|
return FAILED;
|
||||||
pts->add_pcr_entry(pts, entry);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|||||||
+168
-124
@@ -108,9 +108,30 @@ struct private_pts_t {
|
|||||||
certificate_t *aik;
|
certificate_t *aik;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of extended PCR's with corresponding values
|
* Table of extended PCRs with corresponding values
|
||||||
*/
|
*/
|
||||||
linked_list_t *pcrs;
|
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];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(pts_t, get_proto_caps, pts_proto_caps_flag_t,
|
METHOD(pts_t, get_proto_caps, pts_proto_caps_flag_t,
|
||||||
@@ -784,17 +805,32 @@ METHOD(pts_t, extend_pcr, bool,
|
|||||||
DBG3(DBG_PTS, "PCR %d value after extend: %B", pcr_num, output);
|
DBG3(DBG_PTS, "PCR %d value after extend: %B", pcr_num, output);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
chunk_clear(&pcr_value);
|
chunk_clear(&pcr_value);
|
||||||
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
|
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
|
||||||
Tspi_Context_Close(hContext);
|
Tspi_Context_Close(hContext);
|
||||||
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,
|
private_pts_t *this, bool use_quote2, chunk_t *pcr_composite,
|
||||||
u_int32_t *pcrs, u_int32_t num_of_pcrs,
|
chunk_t *quote_signature)
|
||||||
chunk_t *pcr_composite, chunk_t *quote_signature)
|
|
||||||
{
|
{
|
||||||
TSS_HCONTEXT hContext;
|
TSS_HCONTEXT hContext;
|
||||||
TSS_HTPM hTPM;
|
TSS_HTPM hTPM;
|
||||||
@@ -805,10 +841,11 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
BYTE secret[] = TSS_WELL_KNOWN_SECRET;
|
BYTE secret[] = TSS_WELL_KNOWN_SECRET;
|
||||||
TSS_HPCRS hPcrComposite;
|
TSS_HPCRS hPcrComposite;
|
||||||
TSS_VALIDATION valData;
|
TSS_VALIDATION valData;
|
||||||
u_int32_t i, versionInfoSize;
|
|
||||||
TSS_RESULT result;
|
TSS_RESULT result;
|
||||||
chunk_t pcr_comp, quote_sign;
|
chunk_t pcr_comp, quote_sign;
|
||||||
BYTE* versionInfo;
|
BYTE* versionInfo;
|
||||||
|
u_int32_t versionInfoSize, pcr, i = 0, f = 1;
|
||||||
|
bool success = FALSE;
|
||||||
|
|
||||||
result = Tspi_Context_Create(&hContext);
|
result = Tspi_Context_Create(&hContext);
|
||||||
if (result != TSS_SUCCESS)
|
if (result != TSS_SUCCESS)
|
||||||
@@ -866,22 +903,27 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select PCR's */
|
/* Select PCRs */
|
||||||
for (i = 0; i < num_of_pcrs ; i++)
|
for (pcr = 0; pcr <= this->pcr_max ; pcr++)
|
||||||
{
|
{
|
||||||
if (pcrs[i] < 0 || pcrs[i] >= MAX_NUM_PCR )
|
if (f == 256)
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "Invalid PCR number: %d", pcrs[i]);
|
i++;
|
||||||
goto err3;
|
f = 1;
|
||||||
}
|
}
|
||||||
result = use_quote2 ?
|
if (this->pcr_select[i] & f)
|
||||||
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcrs[i],
|
|
||||||
TSS_PCRS_DIRECTION_RELEASE):
|
|
||||||
Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcrs[i]);
|
|
||||||
if (result != TSS_SUCCESS)
|
|
||||||
{
|
{
|
||||||
goto err3;
|
DBG2(DBG_TNC, "PCR %02d selected for TPM Quote", pcr);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the Validation Data */
|
/* Set the Validation Data */
|
||||||
@@ -928,82 +970,106 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
DBG3(DBG_PTS, "TPM Quote Signature: %B",quote_signature);
|
DBG3(DBG_PTS, "TPM Quote Signature: %B",quote_signature);
|
||||||
|
|
||||||
chunk_clear("e_sign);
|
chunk_clear("e_sign);
|
||||||
Tspi_Context_FreeMemory(hContext, NULL);
|
success = TRUE;
|
||||||
Tspi_Context_CloseObject(hContext, hPcrComposite);
|
|
||||||
Tspi_Context_CloseObject(hContext, hAIK);
|
|
||||||
Tspi_Context_Close(hContext);
|
|
||||||
free(pcrs);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
err4:
|
err4:
|
||||||
Tspi_Context_FreeMemory(hContext, NULL);
|
Tspi_Context_FreeMemory(hContext, NULL);
|
||||||
|
|
||||||
err3:
|
err3:
|
||||||
Tspi_Context_CloseObject(hContext, hPcrComposite);
|
Tspi_Context_CloseObject(hContext, hPcrComposite);
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
Tspi_Context_CloseObject(hContext, hAIK);
|
Tspi_Context_CloseObject(hContext, hAIK);
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
Tspi_Context_Close(hContext);
|
Tspi_Context_Close(hContext);
|
||||||
free(pcrs);
|
|
||||||
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
|
if (!success)
|
||||||
return FALSE;
|
{
|
||||||
|
DBG1(DBG_PTS, "TPM not available: tss error 0x%x", result);
|
||||||
|
}
|
||||||
|
clear_pcrs(this);
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_t, add_pcr_entry, void,
|
METHOD(pts_t, select_pcr, bool,
|
||||||
private_pts_t *this, pcr_entry_t *new)
|
private_pts_t *this, u_int32_t pcr)
|
||||||
{
|
{
|
||||||
enumerator_t *e;
|
u_int32_t i, f;
|
||||||
pcr_entry_t *entry;
|
|
||||||
|
|
||||||
if (!this->pcrs)
|
if (pcr >= PCR_MAX_NUM)
|
||||||
{
|
{
|
||||||
this->pcrs = linked_list_create();
|
DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
|
||||||
|
pcr, PCR_MAX_NUM-1);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = this->pcrs->create_enumerator(this->pcrs);
|
/* Determine PCR selection flag */
|
||||||
while (e->enumerate(e, &entry))
|
i = pcr / 8;
|
||||||
|
f = 1 << (pcr - 8*i);
|
||||||
|
|
||||||
|
/* Has this PCR already been selected? */
|
||||||
|
if (!(this->pcr_select[i] & f))
|
||||||
{
|
{
|
||||||
if (entry->pcr_number == new->pcr_number)
|
this->pcr_select[i] |= f;
|
||||||
{
|
this->pcr_max = max(this->pcr_max, pcr);
|
||||||
DBG3(DBG_PTS, "updating already added PCR%d value",
|
this->pcr_count++;
|
||||||
entry->pcr_number);
|
|
||||||
this->pcrs->remove_at(this->pcrs, e);
|
|
||||||
free(entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DESTROY_IF(e);
|
|
||||||
this->pcrs->insert_last(this->pcrs, new);
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
METHOD(pts_t, add_pcr, bool,
|
||||||
* Get the maximum PCR index received in pcr_after_value field
|
private_pts_t *this, u_int32_t pcr, chunk_t pcr_before, chunk_t pcr_after)
|
||||||
*/
|
|
||||||
static u_int32_t get_max_pcr_index(private_pts_t *this)
|
|
||||||
{
|
{
|
||||||
enumerator_t *e;
|
if (pcr >= PCR_MAX_NUM)
|
||||||
pcr_entry_t *pcr_entry;
|
|
||||||
u_int32_t ret = 0;
|
|
||||||
|
|
||||||
if (this->pcrs->get_count(this->pcrs) == 0)
|
|
||||||
{
|
{
|
||||||
return -1;
|
DBG1(DBG_PTS, "PCR %u: number is larger than maximum of %u",
|
||||||
|
pcr, PCR_MAX_NUM-1);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = this->pcrs->create_enumerator(this->pcrs);
|
/* Is the length of the PCR registers already set? */
|
||||||
while (e->enumerate(e, &pcr_entry))
|
if (this->pcr_len)
|
||||||
{
|
{
|
||||||
if (pcr_entry->pcr_number > ret)
|
if (pcr_after.len != this->pcr_len)
|
||||||
{
|
{
|
||||||
ret = pcr_entry->pcr_number;
|
DBG1(DBG_PTS, "PCR %02u: length is %d bytes but should be %d bytes",
|
||||||
|
pcr_after.len, this->pcr_len);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
else
|
||||||
|
{
|
||||||
|
this->pcr_len = pcr_after.len;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_t, does_pcr_value_match, bool,
|
METHOD(pts_t, does_pcr_value_match, bool,
|
||||||
@@ -1052,70 +1118,54 @@ METHOD(pts_t, get_quote_info, bool,
|
|||||||
pts_meas_algorithms_t composite_algo,
|
pts_meas_algorithms_t composite_algo,
|
||||||
chunk_t *out_pcr_composite, chunk_t *out_quote_info)
|
chunk_t *out_pcr_composite, chunk_t *out_quote_info)
|
||||||
{
|
{
|
||||||
enumerator_t *e;
|
u_int8_t size_of_select;
|
||||||
pcr_entry_t *pcr_entry;
|
int pcr_composite_len, i;
|
||||||
chunk_t pcr_composite, hash_pcr_composite;
|
chunk_t pcr_composite, hash_pcr_composite;
|
||||||
u_int32_t pcr_composite_len, i, maximum_pcr_index, bitmask_len;
|
|
||||||
bio_writer_t *writer;
|
bio_writer_t *writer;
|
||||||
hasher_t *hasher;
|
hasher_t *hasher;
|
||||||
|
|
||||||
maximum_pcr_index = get_max_pcr_index(this);
|
if (this->pcr_count == 0)
|
||||||
if (maximum_pcr_index == -1)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "PCR entries unavailable, unable to construct "
|
DBG1(DBG_PTS, "No extended PCR entries available, "
|
||||||
"TPM Quote Info");
|
"unable to construct TPM Quote Info");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!this->secret.ptr)
|
if (!this->secret.ptr)
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "Secret assessment value unavailable",
|
DBG1(DBG_PTS, "Secret assessment value unavailable, ",
|
||||||
"unable to construct TPM Quote Info");
|
"unable to construct TPM Quote Info");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (use_quote2 && ver_info_included && !this->tpm_version_info.ptr)
|
if (use_quote2 && ver_info_included && !this->tpm_version_info.ptr)
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "TPM Version Information unavailable",
|
DBG1(DBG_PTS, "TPM Version Information unavailable, ",
|
||||||
"unable to construct TPM Quote Info2");
|
"unable to construct TPM Quote Info2");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmask_len = maximum_pcr_index/8 +1;
|
size_of_select = 1 + this->pcr_max / 8;
|
||||||
u_int8_t mask_bytes[MAX_NUM_PCR/8] = {0};
|
pcr_composite_len = 2 + size_of_select +
|
||||||
|
4 + this->pcr_count * this->pcr_len;
|
||||||
pcr_composite_len = 2 + bitmask_len + 4 +
|
|
||||||
this->pcrs->get_count(this->pcrs) * PCR_LEN;
|
|
||||||
|
|
||||||
writer = bio_writer_create(pcr_composite_len);
|
writer = bio_writer_create(pcr_composite_len);
|
||||||
/* Lenght of the bist mask field */
|
|
||||||
writer->write_uint16(writer, bitmask_len);
|
|
||||||
/* Bit mask indicating selected PCRs */
|
|
||||||
e = this->pcrs->create_enumerator(this->pcrs);
|
|
||||||
while (e->enumerate(e, &pcr_entry))
|
|
||||||
{
|
|
||||||
u_int32_t index = pcr_entry->pcr_number;
|
|
||||||
mask_bytes[index / 8] |= (1 << (index % 8));
|
|
||||||
}
|
|
||||||
e->destroy(e);
|
|
||||||
|
|
||||||
for (i = 0; i< bitmask_len ; i++)
|
writer->write_uint16(writer, size_of_select);
|
||||||
|
for (i = 0; i < size_of_select; i++)
|
||||||
{
|
{
|
||||||
writer->write_uint8(writer, mask_bytes[i]);
|
writer->write_uint8(writer, this->pcr_select[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lenght of the pcr entries */
|
writer->write_uint32(writer, this->pcr_count * this->pcr_len);
|
||||||
writer->write_uint32(writer, this->pcrs->get_count(this->pcrs) * PCR_LEN);
|
for (i = 0; i < 8 * size_of_select; i++)
|
||||||
/* Actual PCR values */
|
|
||||||
e = this->pcrs->create_enumerator(this->pcrs);
|
|
||||||
while (e->enumerate(e, &pcr_entry))
|
|
||||||
{
|
{
|
||||||
writer->write_data(writer, chunk_create(pcr_entry->pcr_value, PCR_LEN));
|
if (this->pcrs[i])
|
||||||
|
{
|
||||||
|
writer->write_data(writer, chunk_create(this->pcrs[i], this->pcr_len));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(pcr_entry);
|
|
||||||
e->destroy(e);
|
|
||||||
|
|
||||||
/* PCR Composite structure */
|
|
||||||
pcr_composite = chunk_clone(writer->get_buf(writer));
|
pcr_composite = chunk_clone(writer->get_buf(writer));
|
||||||
DBG3(DBG_PTS, "PCR Composite: %B", &pcr_composite);
|
DBG3(DBG_PTS, "PCR Composite: %B", &pcr_composite);
|
||||||
|
|
||||||
writer->destroy(writer);
|
writer->destroy(writer);
|
||||||
|
|
||||||
/* Output the TPM_PCR_COMPOSITE expected from IMC */
|
/* Output the TPM_PCR_COMPOSITE expected from IMC */
|
||||||
@@ -1171,21 +1221,18 @@ METHOD(pts_t, get_quote_info, bool,
|
|||||||
writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2);
|
writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2);
|
||||||
|
|
||||||
/* Magic QUT2 value */
|
/* Magic QUT2 value */
|
||||||
writer->write_uint8(writer, 'Q');
|
writer->write_data(writer, chunk_create("QUT2", 4));
|
||||||
writer->write_uint8(writer, 'U');
|
|
||||||
writer->write_uint8(writer, 'T');
|
|
||||||
writer->write_uint8(writer, '2');
|
|
||||||
|
|
||||||
/* Secret assessment value 20 bytes (nonce) */
|
/* Secret assessment value 20 bytes (nonce) */
|
||||||
writer->write_data(writer, this->secret);
|
writer->write_data(writer, this->secret);
|
||||||
|
|
||||||
/* Lenght of the bist mask field */
|
/* Length of the PCR selection field */
|
||||||
writer->write_uint16(writer, bitmask_len);
|
writer->write_uint16(writer, size_of_select);
|
||||||
|
|
||||||
/* PCR selection Bitmask */
|
/* PCR selection */
|
||||||
for (i = 0; i< bitmask_len ; i++)
|
for (i = 0; i < size_of_select ; i++)
|
||||||
{
|
{
|
||||||
writer->write_uint8(writer, mask_bytes[i]);
|
writer->write_uint8(writer, this->pcr_select[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TPM Locality Selection */
|
/* TPM Locality Selection */
|
||||||
@@ -1203,16 +1250,10 @@ METHOD(pts_t, get_quote_info, bool,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Version number */
|
/* Version number */
|
||||||
writer->write_uint8(writer, 1);
|
writer->write_data(writer, chunk_from_chars(1, 1, 0, 0));
|
||||||
writer->write_uint8(writer, 1);
|
|
||||||
writer->write_uint8(writer, 0);
|
|
||||||
writer->write_uint8(writer, 0);
|
|
||||||
|
|
||||||
/* Magic QUOT value */
|
/* Magic QUOT value */
|
||||||
writer->write_uint8(writer, 'Q');
|
writer->write_data(writer, chunk_create("QUOT", 4));
|
||||||
writer->write_uint8(writer, 'U');
|
|
||||||
writer->write_uint8(writer, 'O');
|
|
||||||
writer->write_uint8(writer, 'T');
|
|
||||||
|
|
||||||
/* PCR Composite Hash */
|
/* PCR Composite Hash */
|
||||||
writer->write_data(writer, hash_pcr_composite);
|
writer->write_data(writer, hash_pcr_composite);
|
||||||
@@ -1227,7 +1268,9 @@ METHOD(pts_t, get_quote_info, bool,
|
|||||||
/* TPM Quote Info */
|
/* TPM Quote Info */
|
||||||
*out_quote_info = chunk_clone(writer->get_buf(writer));
|
*out_quote_info = chunk_clone(writer->get_buf(writer));
|
||||||
DBG3(DBG_PTS, "Calculated TPM Quote Info: %B", out_quote_info);
|
DBG3(DBG_PTS, "Calculated TPM Quote Info: %B", out_quote_info);
|
||||||
|
|
||||||
writer->destroy(writer);
|
writer->destroy(writer);
|
||||||
|
clear_pcrs(this);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1267,9 +1310,9 @@ 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->aik);
|
DESTROY_IF(this->aik);
|
||||||
DESTROY_IF(this->dh);
|
DESTROY_IF(this->dh);
|
||||||
DESTROY_IF(this->pcrs);
|
|
||||||
free(this->initiator_nonce.ptr);
|
free(this->initiator_nonce.ptr);
|
||||||
free(this->responder_nonce.ptr);
|
free(this->responder_nonce.ptr);
|
||||||
free(this->secret.ptr);
|
free(this->secret.ptr);
|
||||||
@@ -1463,7 +1506,8 @@ 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,
|
||||||
.add_pcr_entry = _add_pcr_entry,
|
.select_pcr = _select_pcr,
|
||||||
|
.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,
|
||||||
|
|||||||
+18
-18
@@ -22,7 +22,6 @@
|
|||||||
#define PTS_H_
|
#define PTS_H_
|
||||||
|
|
||||||
typedef struct pts_t pts_t;
|
typedef struct pts_t pts_t;
|
||||||
typedef struct pcr_entry_t pcr_entry_t;
|
|
||||||
|
|
||||||
#include "pts_error.h"
|
#include "pts_error.h"
|
||||||
#include "pts_proto_caps.h"
|
#include "pts_proto_caps.h"
|
||||||
@@ -81,7 +80,7 @@ typedef struct pcr_entry_t pcr_entry_t;
|
|||||||
/**
|
/**
|
||||||
* Maximum number of PCR's of TPM, TPM Spec 1.2
|
* Maximum number of PCR's of TPM, TPM Spec 1.2
|
||||||
*/
|
*/
|
||||||
#define MAX_NUM_PCR 24
|
#define PCR_MAX_NUM 24
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
|
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
|
||||||
@@ -98,14 +97,6 @@ typedef struct pcr_entry_t pcr_entry_t;
|
|||||||
*/
|
*/
|
||||||
#define TRUSTED_HASH_ALGO PTS_MEAS_ALGO_SHA1
|
#define TRUSTED_HASH_ALGO PTS_MEAS_ALGO_SHA1
|
||||||
|
|
||||||
/**
|
|
||||||
* PCR Entry structure which contains PCR number and current value
|
|
||||||
*/
|
|
||||||
struct pcr_entry_t {
|
|
||||||
u_int32_t pcr_number;
|
|
||||||
char pcr_value[PCR_LEN];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class implementing the TCG Platform Trust Service (PTS)
|
* Class implementing the TCG Platform Trust Service (PTS)
|
||||||
*
|
*
|
||||||
@@ -331,23 +322,32 @@ struct pts_t {
|
|||||||
* Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK
|
* Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK
|
||||||
*
|
*
|
||||||
* @param use_quote2 Version of the Quote funtion to be used
|
* @param use_quote2 Version of the Quote funtion to be used
|
||||||
* @param pcrs Array of PCR's to make quotation over
|
|
||||||
* @param num_of_pcrs Number of elements in pcrs array
|
|
||||||
* @param pcr_composite Chunk to save pcr composite structure
|
* @param pcr_composite Chunk to save pcr composite structure
|
||||||
* @param quote_signature Chunk to save quote operation output
|
* @param quote_signature Chunk to save quote operation output
|
||||||
* without external data (anti-replay protection)
|
* without external data (anti-replay protection)
|
||||||
* @return FALSE in case of TSS error, TRUE otherwise
|
* @return FALSE in case of TSS error, TRUE otherwise
|
||||||
*/
|
*/
|
||||||
bool (*quote_tpm)(pts_t *this, bool use_quote2,
|
bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_composite,
|
||||||
u_int32_t *pcrs, u_int32_t num_of_pcrs,
|
chunk_t *quote_signature);
|
||||||
chunk_t *pcr_composite, chunk_t *quote_signature);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add extended PCR with its corresponding value
|
* Mark an extended PCR as selected
|
||||||
*
|
*
|
||||||
* @return FALSE in case of any error or non-match, TRUE otherwise
|
* @param pcr Number of the extended PCR
|
||||||
|
* @return TRUE if PCR number is valid
|
||||||
*/
|
*/
|
||||||
void (*add_pcr_entry)(pts_t *this, pcr_entry_t *entry);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs and returns TPM Quote Info structure expected from IMC
|
* Constructs and returns TPM Quote Info structure expected from IMC
|
||||||
|
|||||||
Reference in New Issue
Block a user