Improved implementation of Read PCR/ Extend PCR/ Quote_TPM functions
Implemented creating/handling of Simple Evidence Final attribute (incomplete)
This commit is contained in:
committed by
Andreas Steffen
parent
e1aebc940a
commit
924f3bf59e
@@ -409,7 +409,7 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
selected_dh_group = pts->get_dh_group(pts);
|
selected_dh_group = pts->get_dh_group(pts);
|
||||||
if (!pts->create_dh(pts, selected_dh_group))
|
if (!pts->create_dh(pts, selected_dh_group))
|
||||||
{
|
{
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
pts->get_my_pub_val(pts, &responder_pub_val);
|
pts->get_my_pub_val(pts, &responder_pub_val);
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
if (!pts->calculate_secret(pts, initiator_nonce,
|
if (!pts->calculate_secret(pts, initiator_nonce,
|
||||||
responder_non, selected_algorithm))
|
responder_non, selected_algorithm))
|
||||||
{
|
{
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -672,13 +672,13 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_IMC, " hasher %N not available",
|
DBG1(DBG_IMC, " hasher %N not available",
|
||||||
hash_algorithm_names, hash_alg);
|
hash_algorithm_names, hash_alg);
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pts->hash_file(pts, hasher, "/etc/tnc_config", hash_output))
|
if (!pts->hash_file(pts, hasher, "/etc/tnc_config", hash_output))
|
||||||
{
|
{
|
||||||
hasher->destroy(hasher);
|
hasher->destroy(hasher);
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
measurement_time_t = time(NULL);
|
measurement_time_t = time(NULL);
|
||||||
@@ -698,9 +698,13 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
time_now->tm_sec) < 0)
|
time_now->tm_sec) < 0)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMC, "Couldn not format local time to UTC");
|
DBG1(DBG_IMC, "Couldn not format local time to UTC");
|
||||||
return TNC_RESULT_FATAL;
|
hasher->destroy(hasher);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
params.measurement_time = chunk_create(utc_time, 20);
|
params.measurement_time = chunk_create(utc_time, 20);
|
||||||
|
params.measurement_time = chunk_clone(params.measurement_time);
|
||||||
|
free(utc_time);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
params.measurement = chunk_create(hash_output, hasher->get_hash_size(hasher));
|
params.measurement = chunk_create(hash_output, hasher->get_hash_size(hasher));
|
||||||
@@ -710,13 +714,14 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
if (!pts->read_pcr(pts, EXTEND_PCR, ¶ms.pcr_before))
|
if (!pts->read_pcr(pts, EXTEND_PCR, ¶ms.pcr_before))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMC, "Error occured while reading PCR: %d", EXTEND_PCR);
|
DBG1(DBG_IMC, "Error occured while reading PCR: %d", EXTEND_PCR);
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pts->extend_pcr(pts, EXTEND_PCR,
|
if (!pts->extend_pcr(pts, EXTEND_PCR,
|
||||||
params.measurement, ¶ms.pcr_after))
|
params.measurement, ¶ms.pcr_after))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMC, "Error occured while extending PCR: %d", EXTEND_PCR);
|
DBG1(DBG_IMC, "Error occured while extending PCR: %d", EXTEND_PCR);
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buffer Simple Component Evidence attribute */
|
/* Buffer Simple Component Evidence attribute */
|
||||||
@@ -744,22 +749,47 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
{
|
{
|
||||||
enumerator_t *e;
|
enumerator_t *e;
|
||||||
pts_simple_evid_final_flag_t flags;
|
pts_simple_evid_final_flag_t flags;
|
||||||
|
chunk_t pcr_composite, quote_signature;
|
||||||
|
linked_list_t *pcrs;
|
||||||
|
|
||||||
/* Send buffered Simple Component Evidences */
|
/* Send buffered Simple Component Evidences */
|
||||||
|
pcrs = linked_list_create();
|
||||||
|
|
||||||
e = evidences->create_enumerator(evidences);
|
e = evidences->create_enumerator(evidences);
|
||||||
while (e->enumerate(e, &attr))
|
while (e->enumerate(e, &attr))
|
||||||
{
|
{
|
||||||
|
tcg_pts_attr_simple_comp_evid_t *attr_cast;
|
||||||
|
u_int32_t extended_pcr;
|
||||||
|
|
||||||
|
attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
|
||||||
|
extended_pcr = attr_cast->get_extended_pcr(attr_cast);
|
||||||
|
|
||||||
|
/* Add extended PCR number to PCR list to quote */
|
||||||
|
/* Duplicated PCR numbers have no influence */
|
||||||
|
pcrs->insert_last(pcrs, &extended_pcr);
|
||||||
|
/* Send Simple Compoenent Evidence */
|
||||||
attr_list->insert_last(attr_list, attr);
|
attr_list->insert_last(attr_list, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: TPM quote operation over included PCR's */
|
/* Quote */
|
||||||
|
if (!pts->quote_tpm(pts, pcrs, &pcr_composite, "e_signature))
|
||||||
|
{
|
||||||
|
DBG1(DBG_IMC, "Error occured while TPM quote operation");
|
||||||
|
DESTROY_IF(e);
|
||||||
|
DESTROY_IF(pcrs);
|
||||||
|
DESTROY_IF(evidences);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send Simple Evidence Final attribute */
|
/* Send Simple Evidence Final attribute */
|
||||||
flags = PTS_SIMPLE_EVID_FINAL_FLAG_NO;
|
flags = PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO;
|
||||||
|
|
||||||
attr = tcg_pts_attr_simple_evid_final_create(flags, 0,
|
attr = tcg_pts_attr_simple_evid_final_create(flags, 0,
|
||||||
chunk_empty, chunk_empty, chunk_empty);
|
pcr_composite, quote_signature, chunk_empty);
|
||||||
attr_list->insert_last(attr_list, attr);
|
attr_list->insert_last(attr_list, attr);
|
||||||
|
|
||||||
e->destroy(e);
|
DESTROY_IF(e);
|
||||||
|
DESTROY_IF(pcrs);
|
||||||
DESTROY_IF(evidences);
|
DESTROY_IF(evidences);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -806,7 +836,7 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
if (!metadata)
|
if (!metadata)
|
||||||
{
|
{
|
||||||
/* TODO handle error codes from measurements */
|
/* TODO handle error codes from measurements */
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
attr = tcg_pts_attr_unix_file_meta_create(metadata);
|
attr = tcg_pts_attr_unix_file_meta_create(metadata);
|
||||||
attr->set_noskip_flag(attr, TRUE);
|
attr->set_noskip_flag(attr, TRUE);
|
||||||
@@ -862,7 +892,7 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
if (!measurements)
|
if (!measurements)
|
||||||
{
|
{
|
||||||
/* TODO handle error codes from measurements */
|
/* TODO handle error codes from measurements */
|
||||||
return TNC_RESULT_FATAL;
|
goto err;
|
||||||
}
|
}
|
||||||
attr = tcg_pts_attr_file_meas_create(measurements);
|
attr = tcg_pts_attr_file_meas_create(measurements);
|
||||||
attr->set_noskip_flag(attr, TRUE);
|
attr->set_noskip_flag(attr, TRUE);
|
||||||
@@ -918,9 +948,13 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
|||||||
pa_tnc_msg->get_encoding(pa_tnc_msg));
|
pa_tnc_msg->get_encoding(pa_tnc_msg));
|
||||||
pa_tnc_msg->destroy(pa_tnc_msg);
|
pa_tnc_msg->destroy(pa_tnc_msg);
|
||||||
}
|
}
|
||||||
attr_list->destroy(attr_list);
|
|
||||||
|
|
||||||
|
DESTROY_IF(attr_list);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
err:
|
||||||
|
DESTROY_IF(attr_list);
|
||||||
|
return TNC_RESULT_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -750,9 +750,31 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
|
|||||||
|
|
||||||
case TCG_PTS_SIMPLE_EVID_FINAL:
|
case TCG_PTS_SIMPLE_EVID_FINAL:
|
||||||
{
|
{
|
||||||
/** TODO: Implement construct Quote structure over saved values from
|
tcg_pts_attr_simple_evid_final_t *attr_cast;
|
||||||
* TCG_PTS_SIMPLE_COMP_EVID and compare with received one
|
pts_simple_evid_final_flag_t flags;
|
||||||
|
chunk_t pcr_comp = chunk_empty;
|
||||||
|
chunk_t tpm_quote_sign = chunk_empty;
|
||||||
|
chunk_t evid_sign = chunk_empty;
|
||||||
|
|
||||||
|
/** TODO: Ignoring Composite Hash Algorithm field
|
||||||
|
* No flag defined which indicates the precense of it
|
||||||
*/
|
*/
|
||||||
|
attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
|
||||||
|
flags = attr_cast->get_flags(attr_cast);
|
||||||
|
|
||||||
|
if ((flags >> 6) & PTS_SIMPLE_EVID_FINAL_FLAG_NO)
|
||||||
|
{
|
||||||
|
pcr_comp = attr_cast->get_pcr_comp(attr_cast);
|
||||||
|
tpm_quote_sign = attr_cast->get_tpm_quote_sign(attr_cast);
|
||||||
|
|
||||||
|
/** TODO: Construct PCR Composite */
|
||||||
|
}
|
||||||
|
if (flags & PTS_SIMPLE_EVID_FINAL_FLAG_EVID)
|
||||||
|
{
|
||||||
|
/** TODO: What to do with Evidence Signature */
|
||||||
|
evid_sign = attr_cast->get_evid_sign(attr_cast);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-8
@@ -650,6 +650,7 @@ METHOD(pts_t, read_pcr, bool,
|
|||||||
{
|
{
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
pcr_value = chunk_alloc(PCR_LEN);
|
||||||
result = Tspi_TPM_PcrRead(hTPM, pcr_num, &pcr_length, &pcr_value.ptr);
|
result = Tspi_TPM_PcrRead(hTPM, pcr_num, &pcr_length, &pcr_value.ptr);
|
||||||
if (result != TSS_SUCCESS)
|
if (result != TSS_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -659,11 +660,13 @@ METHOD(pts_t, read_pcr, bool,
|
|||||||
*output = pcr_value;
|
*output = pcr_value;
|
||||||
*output = chunk_clone(*output);
|
*output = chunk_clone(*output);
|
||||||
|
|
||||||
|
chunk_clear(&pcr_value);
|
||||||
Tspi_Context_Close(hContext);
|
Tspi_Context_Close(hContext);
|
||||||
DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, output);
|
DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, output);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
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;
|
||||||
@@ -694,7 +697,10 @@ METHOD(pts_t, extend_pcr, bool,
|
|||||||
{
|
{
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
result = Tspi_TPM_PcrExtend(hTPM, pcr_num, 20, input.ptr, NULL, &pcr_length, &pcr_value.ptr);
|
|
||||||
|
pcr_value = chunk_alloc(PCR_LEN);
|
||||||
|
result = Tspi_TPM_PcrExtend(hTPM, pcr_num, PCR_LEN, input.ptr,
|
||||||
|
NULL, &pcr_length, &pcr_value.ptr);
|
||||||
if (result != TSS_SUCCESS)
|
if (result != TSS_SUCCESS)
|
||||||
{
|
{
|
||||||
goto err;
|
goto err;
|
||||||
@@ -703,20 +709,21 @@ METHOD(pts_t, extend_pcr, bool,
|
|||||||
*output = pcr_value;
|
*output = pcr_value;
|
||||||
*output = chunk_clone(*output);
|
*output = chunk_clone(*output);
|
||||||
|
|
||||||
|
chunk_clear(&pcr_value);
|
||||||
Tspi_Context_Close(hContext);
|
Tspi_Context_Close(hContext);
|
||||||
DBG3(DBG_PTS, "PCR %d extended with: %B", pcr_num, &input);
|
DBG3(DBG_PTS, "PCR %d extended with: %B", pcr_num, &input);
|
||||||
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);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_t, quote_tpm, bool,
|
METHOD(pts_t, quote_tpm, bool,
|
||||||
private_pts_t *this, u_int32_t *pcrs, u_int32_t num_of_pcrs,
|
private_pts_t *this, linked_list_t *pcrs,
|
||||||
chunk_t *pcr_composite, chunk_t *quote_signature)
|
chunk_t *pcr_composite, chunk_t *quote_signature)
|
||||||
{
|
{
|
||||||
TSS_HCONTEXT hContext;
|
TSS_HCONTEXT hContext;
|
||||||
@@ -729,10 +736,11 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
TSS_HPCRS hPcrComposite;
|
TSS_HPCRS hPcrComposite;
|
||||||
TSS_VALIDATION valData;
|
TSS_VALIDATION valData;
|
||||||
TPM_QUOTE_INFO *quoteInfo;
|
TPM_QUOTE_INFO *quoteInfo;
|
||||||
u_int32_t i;
|
u_int32_t i, pcr;
|
||||||
TSS_RESULT result;
|
TSS_RESULT result;
|
||||||
chunk_t aik_key_encoding;
|
chunk_t aik_key_encoding;
|
||||||
chunk_t pcr_composite_without_nonce;
|
chunk_t pcr_composite_without_nonce;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
result = Tspi_Context_Create(&hContext);
|
result = Tspi_Context_Create(&hContext);
|
||||||
if (result != TSS_SUCCESS)
|
if (result != TSS_SUCCESS)
|
||||||
@@ -774,7 +782,7 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
/* Create from AIK public key a HKEY object to sign Quote operation output*/
|
/* Create from AIK public key a HKEY object to sign Quote operation output*/
|
||||||
if (this->aik->get_type(this->aik) == CERT_TRUSTED_PUBKEY)
|
if (this->aik->get_type(this->aik) == CERT_TRUSTED_PUBKEY)
|
||||||
{
|
{
|
||||||
if (!this->aik->get_encoding(this->aik, CERT_ASN1_DER, &aik_key_encoding))
|
if (!this->aik->get_encoding(this->aik, CERT_PEM, &aik_key_encoding))
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "encoding AIK certificate for quote operation failed");
|
DBG1(DBG_PTS, "encoding AIK certificate for quote operation failed");
|
||||||
goto err1;
|
goto err1;
|
||||||
@@ -789,7 +797,7 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
DBG1(DBG_PTS, "unable to retrieve public key from AIK certificate");
|
DBG1(DBG_PTS, "unable to retrieve public key from AIK certificate");
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
if (!key->get_encoding(key, PUBKEY_ASN1_DER, &aik_key_encoding))
|
if (!key->get_encoding(key, PUBKEY_PEM, &aik_key_encoding))
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "encoding AIK Public Key for quote operation failed");
|
DBG1(DBG_PTS, "encoding AIK Public Key for quote operation failed");
|
||||||
goto err1;
|
goto err1;
|
||||||
@@ -816,9 +824,9 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Select PCR's */
|
/* Select PCR's */
|
||||||
for (i = 0; i < num_of_pcrs; i++)
|
enumerator = pcrs->create_enumerator(pcrs);
|
||||||
|
while (enumerator->enumerate(enumerator, &pcr))
|
||||||
{
|
{
|
||||||
u_int32_t pcr = pcrs[i];
|
|
||||||
if (pcr < 0 || pcr >= MAX_NUM_PCR )
|
if (pcr < 0 || pcr >= MAX_NUM_PCR )
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "Invalid PCR number: %d", pcr);
|
DBG1(DBG_PTS, "Invalid PCR number: %d", pcr);
|
||||||
@@ -830,6 +838,7 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
/* Set the Validation Data */
|
/* Set the Validation Data */
|
||||||
valData.ulExternalDataLength = this->secret.len;
|
valData.ulExternalDataLength = this->secret.len;
|
||||||
@@ -872,6 +881,9 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
memcpy(pcr_composite_without_nonce.ptr, valData.rgbData,
|
memcpy(pcr_composite_without_nonce.ptr, valData.rgbData,
|
||||||
valData.ulDataLength - ASSESSMENT_SECRET_LEN);
|
valData.ulDataLength - ASSESSMENT_SECRET_LEN);
|
||||||
*pcr_composite = pcr_composite_without_nonce;
|
*pcr_composite = pcr_composite_without_nonce;
|
||||||
|
*pcr_composite = chunk_clone(*pcr_composite);
|
||||||
|
free(pcr_composite_without_nonce.ptr);
|
||||||
|
|
||||||
*quote_signature = chunk_from_thing(valData.rgbValidationData);
|
*quote_signature = chunk_from_thing(valData.rgbValidationData);
|
||||||
*quote_signature = chunk_clone(*quote_signature);
|
*quote_signature = chunk_clone(*quote_signature);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ typedef struct pts_t pts_t;
|
|||||||
#include "pts_dh_group.h"
|
#include "pts_dh_group.h"
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UTF-8 encoding of the character used to delimiter the filename
|
* UTF-8 encoding of the character used to delimiter the filename
|
||||||
@@ -53,6 +54,11 @@ typedef struct pts_t pts_t;
|
|||||||
*/
|
*/
|
||||||
#define MAX_NUM_PCR 24
|
#define MAX_NUM_PCR 24
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes can be savedin a PCR of TPM, TPM Spec 1.2
|
||||||
|
*/
|
||||||
|
#define PCR_LEN 20
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class implementing the TCG Platform Trust System (PTS)
|
* Class implementing the TCG Platform Trust System (PTS)
|
||||||
*
|
*
|
||||||
@@ -249,14 +255,13 @@ struct pts_t {
|
|||||||
* Quote over PCR's
|
* Quote over PCR's
|
||||||
* 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 pcrs Set of PCR's to make quotation over
|
* @param pcrs List of PCR's to make quotation over
|
||||||
* @param num_of_pcr Number of PCR's
|
|
||||||
* @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, u_int32_t *pcrs, u_int32_t num_of_pcrs,
|
bool (*quote_tpm)(pts_t *this, linked_list_t *pcrs,
|
||||||
chunk_t *pcr_composite, chunk_t *quote_signature);
|
chunk_t *pcr_composite, chunk_t *quote_signature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user