libimcv.plugins.imc-attestation.aik_handle =
AIK object handle.
+libimcv.plugins.imc-attestation.hash_algorithm = sha384
+ Preferred measurement hash algorithm.
+
libimcv.plugins.imc-attestation.mandatory_dh_groups = yes
Enforce mandatory Diffie-Hellman groups.
libimcv.plugins.imv-attestation.dh_group = ecp256
Preferred Diffie-Hellman group.
-libimcv.plugins.imv-attestation.hash_algorithm = sha256
+libimcv.plugins.imv-attestation.hash_algorithm = sha384
Preferred measurement hash algorithm.
libimcv.plugins.imv-attestation.min_nonce_len = 0
chunk_t attr_info;
pts_t *pts;
pts_error_code_t pts_error;
+ tpm_tss_t *tpm;
pen_type_t attr_type;
+ char *hash_alg;
bool valid_path;
pts = attestation_state->get_pts(attestation_state);
tcg_pts_attr_meas_algo_t *attr_cast;
pts_meas_algorithms_t offered_algorithms, selected_algorithm;
+
attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
offered_algorithms = attr_cast->get_algorithms(attr_cast);
+
+ /* If a TPM is present choose only algorithms with a PCR bank */
+ tpm = pts->get_tpm(pts);
+ if (tpm)
+ {
+ pts_meas_algo_with_pcr(tpm, &supported_algorithms);
+ }
+
+ /* The algorithms can be restricted by the Attestation IMC */
+ hash_alg = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-attestation.hash_algorithm", "sha384", lib->ns);
+ if (!pts_meas_algo_update(hash_alg, &supported_algorithms))
+ {
+ supported_algorithms = PTS_MEAS_ALGO_NONE;
+ }
selected_algorithm = pts_meas_algo_select(supported_algorithms,
offered_algorithms);
if (selected_algorithm == PTS_MEAS_ALGO_NONE)
/* Send DH Nonce Parameters Response attribute */
attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group,
- supported_algorithms, responder_nonce, responder_value);
+ pts->get_meas_algorithm(pts), responder_nonce,
+ responder_value);
msg->add_attribute(msg, attr);
break;
}
}
hash_alg = lib->settings->get_str(lib->settings,
- "%s.plugins.imv-attestation.hash_algorithm", "sha256", lib->ns);
+ "%s.plugins.imv-attestation.hash_algorithm", "sha2384", lib->ns);
dh_group = lib->settings->get_str(lib->settings,
"%s.plugins.imv-attestation.dh_group", "ecp256", lib->ns);
mandatory_dh_groups = lib->settings->get_bool(lib->settings,
}
/* Send DH nonce finish attribute */
- selected_algorithm = pts->get_meas_algorithm(pts);
+ selected_algorithm = pts->get_dh_hash_algorithm(pts);
if (!pts->get_my_public_value(pts, &initiator_value,
&initiator_nonce))
{
uint8_t qualifier, pts_pcr_t *pcrs,
uint32_t pcr, chunk_t measurement)
{
- size_t pcr_len;
pts_pcr_transform_t pcr_transform;
- pts_meas_algorithms_t hash_algo;
+ pts_meas_algorithms_t pcr_algo;
pts_comp_func_name_t *name;
pts_comp_evidence_t *evidence;
chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
- hash_algo = PTS_MEAS_ALGO_SHA1;
- pcr_len = HASH_SIZE_SHA1;
- pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
+ pcr_algo = pcrs->get_pcr_algo(pcrs);
+ pcr_transform = PTS_PCR_TRANSFORM_MATCH;
if (this->pcr_info)
{
}
name = this->name->clone(this->name);
name->set_qualifier(name, qualifier);
- evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
+ evidence = pts_comp_evidence_create(name, this->depth, pcr, pcr_algo,
pcr_transform, this->creation_time, measurement);
if (this->pcr_info)
{
{
case IMA_STATE_INIT:
this->bios_list = pts_ima_bios_list_create(pts->get_tpm(pts),
- IMA_BIOS_MEASUREMENTS);
+ IMA_BIOS_MEASUREMENTS,
+ pcrs->get_pcr_algo(pcrs));
if (!this->bios_list)
{
return FAILED;
return FALSE;
}
hasher->destroy(hasher);
-
- /* The DH secret must be destroyed */
chunk_clear(&shared_secret);
- /*
- * Truncate the hash to 20 bytes to fit the ExternalData
- * argument of the TPM Quote command
- */
- this->secret.len = min(this->secret.len, 20);
DBG3(DBG_PTS, "secret assessment value: %B", &this->secret);
+
return TRUE;
}
tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
{
chunk_t pcr_value, pcr_computed;
+ hash_algorithm_t hash_alg;
uint32_t pcr, pcr_sel = 0;
enumerator_t *enumerator;
+ hash_alg = pts_meas_algo_to_hash(this->pcrs->get_pcr_algo(this->pcrs));
+
/* select PCRs */
DBG2(DBG_PTS, "PCR values hashed into PCR Composite:");
enumerator = this->pcrs->create_enumerator(this->pcrs);
while (enumerator->enumerate(enumerator, &pcr))
{
- if (this->tpm->read_pcr(this->tpm, pcr, &pcr_value, HASH_SHA1))
+ if (this->tpm->read_pcr(this->tpm, pcr, &pcr_value, hash_alg))
{
pcr_computed = this->pcrs->get(this->pcrs, pcr);
DBG2(DBG_PTS, "PCR %2d %#B %s", pcr, &pcr_value,
enumerator->destroy(enumerator);
/* TPM Quote */
- return this->tpm->quote(this->tpm, this->aik_handle, pcr_sel, HASH_SHA1,
+ return this->tpm->quote(this->tpm, this->aik_handle, pcr_sel, hash_alg,
this->secret, quote_mode, quote_info, quote_sig);
}
{
if (!this->pcrs)
{
- this->pcrs = pts_pcr_create(this->tpm_version);
+ this->pcrs = pts_pcr_create(this->tpm_version, this->algorithm);
}
return this->pcrs;
}
},
.is_imc = is_imc,
.proto_caps = PTS_PROTO_CAPS_V,
- .algorithm = PTS_MEAS_ALGO_SHA256,
- .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
+ .algorithm = PTS_MEAS_ALGO_SHA384,
+ .dh_hash_algorithm = PTS_MEAS_ALGO_SHA384,
);
if (is_imc)
/**
* See header
*/
-pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file)
+pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file,
+ pts_meas_algorithms_t algo)
{
private_pts_ima_bios_list_t *this;
uint32_t pcr, ev_type, event_type, event_len, seek_len, count = 1;
uint32_t buf_len = 8192;
uint8_t event_buf[buf_len];
+ hash_algorithm_t hash_alg;
chunk_t event;
bios_entry_t *entry;
struct stat st;
close(fd);
return FALSE;
}
+ hash_alg = pts_meas_algo_to_hash(algo);
INIT(this,
.public = {
{
break;
}
- if (!tpm->get_event_digest(tpm, fd, &entry->measurement))
+ if (!tpm->get_event_digest(tpm, fd, hash_alg, &entry->measurement))
{
break;
}
#ifndef PTS_IMA_BIOS_LIST_H_
#define PTS_IMA_BIOS_LIST_H_
+#include "pts_meas_algo.h"
+
#include <time.h>
#include <library.h>
*
* @param tpm TPM object
* @param file Pathname pointing to the BIOS measurements
+ * @param algo hash measurement algorithm to be used
*/
-pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file);
+pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file,
+ pts_meas_algorithms_t algo);
+
#endif /** PTS_IMA_BIOS_LIST_H_ @}*/
ENUM_BEGIN(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_NONE,
"None");
-ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA512, PTS_MEAS_ALGO_SHA512,
PTS_MEAS_ALGO_NONE,
+ "SHA512");
+ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
+ PTS_MEAS_ALGO_SHA512,
"SHA384");
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
PTS_MEAS_ALGO_SHA384,
DBG2(DBG_PTS, format1, "optional ", hash_algorithm_names, hash_alg,
plugin_name);
}
+ else if (hash_alg == HASH_SHA512)
+ {
+ *algorithms |= PTS_MEAS_ALGO_SHA512;
+ DBG2(DBG_PTS, format1, "optional ", hash_algorithm_names, hash_alg,
+ plugin_name);
+ }
}
enumerator->destroy(enumerator);
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA512))
+ {
+ DBG1(DBG_PTS, format2, "optional ", hash_algorithm_names, HASH_SHA512);
+ }
if (!(*algorithms & PTS_MEAS_ALGO_SHA384))
{
DBG1(DBG_PTS, format2, "optional ", hash_algorithm_names, HASH_SHA384);
{
return TRUE;
}
- if (!(*algorithms & PTS_MEAS_ALGO_SHA1))
- {
- DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA1);
- }
if (!(*algorithms & PTS_MEAS_ALGO_SHA256))
{
DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA256);
}
+ if (!(*algorithms & PTS_MEAS_ALGO_SHA1))
+ {
+ DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA1);
+ }
return FALSE;
}
*/
bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms)
{
- if (strcaseeq(hash_alg, "sha384") || strcaseeq(hash_alg, "sha2_384"))
+ if (strcaseeq(hash_alg, "sha512") || strcaseeq(hash_alg, "sha2_512"))
{
/* nothing to update, all algorithms are supported */
return TRUE;
}
+ if (strcaseeq(hash_alg, "sha384") || strcaseeq(hash_alg, "sha2_384"))
+ {
+ /* remove SHA512 algorithm */
+ *algorithms &= ~PTS_MEAS_ALGO_SHA512;
+ return TRUE;
+ }
if (strcaseeq(hash_alg, "sha256") || strcaseeq(hash_alg, "sha2_256"))
{
- /* remove SHA384algorithm */
- *algorithms &= ~PTS_MEAS_ALGO_SHA384;
+ /* remove SHA512 and SHA384 algorithms */
+ *algorithms &= ~(PTS_MEAS_ALGO_SHA512 | PTS_MEAS_ALGO_SHA384);
return TRUE;
}
if (strcaseeq(hash_alg, "sha1"))
{
- /* remove SHA384 and SHA256 algorithms */
- *algorithms &= ~(PTS_MEAS_ALGO_SHA384 | PTS_MEAS_ALGO_SHA256);
+ /* remove SHA512, SHA384 and SHA256 algorithms */
+ *algorithms &= ~(PTS_MEAS_ALGO_SHA512 | PTS_MEAS_ALGO_SHA384 |
+ PTS_MEAS_ALGO_SHA256);
return TRUE;
}
DBG1(DBG_PTS, "unknown hash algorithm '%s' configured", hash_alg);
return FALSE;
}
+/**
+ * Described in header.
+ */
+void pts_meas_algo_with_pcr(tpm_tss_t *tpm, pts_meas_algorithms_t *algorithms)
+{
+ pts_meas_algorithms_t algo_set[] = { PTS_MEAS_ALGO_SHA1,
+ PTS_MEAS_ALGO_SHA256,
+ PTS_MEAS_ALGO_SHA384,
+ PTS_MEAS_ALGO_SHA512
+ };
+ int i;
+
+ for (i = 0; i < countof(algo_set); i++)
+ {
+ if (!tpm->has_pcr_bank(tpm, pts_meas_algo_to_hash(algo_set[i])))
+ {
+ /* remove algorithm */
+ *algorithms &= ~algo_set[i];
+ }
+ }
+}
+
/**
* Described in header.
*/
pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
pts_meas_algorithms_t offered_algos)
{
+ if ((supported_algos & PTS_MEAS_ALGO_SHA512) &&
+ (offered_algos & PTS_MEAS_ALGO_SHA512))
+ {
+ return PTS_MEAS_ALGO_SHA512;
+ }
if ((supported_algos & PTS_MEAS_ALGO_SHA384) &&
(offered_algos & PTS_MEAS_ALGO_SHA384))
{
return HASH_SHA256;
case PTS_MEAS_ALGO_SHA384:
return HASH_SHA384;
+ case PTS_MEAS_ALGO_SHA512:
+ return HASH_SHA512;
default:
return HASH_UNKNOWN;
}
return PTS_MEAS_ALGO_SHA256;
case HASH_SHA384:
return PTS_MEAS_ALGO_SHA384;
+ case HASH_SHA512:
+ return PTS_MEAS_ALGO_SHA512;
default:
return PTS_MEAS_ALGO_NONE;
}
return HASH_SIZE_SHA256;
case PTS_MEAS_ALGO_SHA384:
return HASH_SIZE_SHA384;
+ case PTS_MEAS_ALGO_SHA512:
+ return HASH_SIZE_SHA512;
case PTS_MEAS_ALGO_NONE:
default:
return 0;
}
}
-
#include <library.h>
#include <crypto/hashers/hasher.h>
+#include <tpm_tss.h>
typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
*/
enum pts_meas_algorithms_t {
PTS_MEAS_ALGO_NONE = 0,
+ PTS_MEAS_ALGO_SHA512 = (1<<12),
PTS_MEAS_ALGO_SHA384 = (1<<13),
PTS_MEAS_ALGO_SHA256 = (1<<14),
PTS_MEAS_ALGO_SHA1 = (1<<15)
* sha1 : PTS_MEAS_ALGO_SHA1
* sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
* sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
+ * sha512: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384 |
+ PTS_MEAS_ALGO_SHA512
*
* The PTS-IMC is expected to select the strongest supported algorithm
*
*/
bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms);
+/**
+ * Remove the PTS measurement algorithms not having an assigned PCR bank
+ *
+ * @param tpm handle to TPM object
+ * @param algorithm reduced set of algorithms with assigned PCR banks
+ * @
+ */
+void pts_meas_algo_with_pcr(tpm_tss_t *tpm, pts_meas_algorithms_t *algorithms);
+
/**
* Select the strongest PTS measurement algorithm
* among a set of offered PTS measurement algorithms
/*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2020 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
*/
uint8_t pcr_select[PTS_PCR_MAX_NUM / 8];
+ /**
+ * Length in bytes of a PCR register (size of hash used)
+ */
+ size_t pcr_len;
+
+ /**
+ * Hash algorithm of PCR bank
+ */
+ pts_meas_algorithms_t pcr_algo;
+
/**
* Hasher used to extend shadow PCRs
*/
};
+METHOD(pts_pcr_t, get_pcr_algo, pts_meas_algorithms_t,
+ private_pts_pcr_t *this)
+{
+ return this->pcr_algo;
+}
+
METHOD(pts_pcr_t, get_count, uint32_t,
private_pts_pcr_t *this)
{
METHOD(pts_pcr_t, set, bool,
private_pts_pcr_t *this, uint32_t pcr, chunk_t value)
{
- if (value.len != PTS_PCR_LEN)
+ if (value.len != this->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);
+ memcpy(this->pcrs[pcr].ptr, value.ptr, this->pcr_len);
return TRUE;
}
return FALSE;
METHOD(pts_pcr_t, extend, chunk_t,
private_pts_pcr_t *this, uint32_t pcr, chunk_t measurement)
{
- if (measurement.len != PTS_PCR_LEN)
+ if (measurement.len != this->pcr_len)
{
DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
return chunk_empty;
u_char *pos;
selection_size = get_selection_size(this);
- pcr_field_size = this->pcr_count * PTS_PCR_LEN;
+ pcr_field_size = this->pcr_count * this->pcr_len;
INIT(pcr_composite,
.pcr_select = chunk_alloc(selection_size),
enumerator = create_enumerator(this);
while (enumerator->enumerate(enumerator, &pcr))
{
- memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
- pos += PTS_PCR_LEN;
+ memcpy(pos, this->pcrs[pcr].ptr, this->pcr_len);
+ pos += this->pcr_len;
}
enumerator->destroy(enumerator);
/**
* See header
*/
-pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version)
+pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version, pts_meas_algorithms_t algo)
{
private_pts_pcr_t *this;
+ hash_algorithm_t hash_alg;
hasher_t *hasher;
uint32_t i;
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ hash_alg = pts_meas_algo_to_hash(algo);
+ hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
if (!hasher)
{
DBG1(DBG_PTS, "%N hasher could not be created",
- hash_algorithm_short_names, HASH_SHA1);
+ hash_algorithm_short_names, hash_alg);
return NULL;
}
INIT(this,
.public = {
+ .get_pcr_algo = _get_pcr_algo,
.get_count = _get_count,
.select_pcr = _select_pcr,
.get_selection_size = _get_selection_size,
.get_composite = _get_composite,
.destroy = _destroy,
},
+ .pcr_algo = algo,
+ .pcr_len = pts_meas_algo_hash_size(algo),
.hasher = hasher,
);
for (i = 0; i < PTS_PCR_MAX_NUM; i++)
{
- this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
- memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
+ this->pcrs[i] = chunk_alloc(this->pcr_len);
+ memset(this->pcrs[i].ptr, 0x00, this->pcr_len);
}
/* Set locality indicator in PCR[0] */
DBG2(DBG_PTS, "TPM 2.0 - locality indicator set to %u",
(uint32_t)locality);
- this->pcrs[0].ptr[PTS_PCR_LEN - 1] = locality;
+ this->pcrs[0].ptr[this->pcr_len - 1] = locality;
}
return &this->public;
typedef struct pts_pcr_t pts_pcr_t;
+#include "pts_meas_algo.h"
+
#include <library.h>
#include <tpm_tss.h>
*/
#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 hash algorithm used by the PCR bank
+ *
+ * @return hash_measurement algorithm
+ */
+ pts_meas_algorithms_t(*get_pcr_algo)(pts_pcr_t *this);
+
/**
* Get the number of selected PCRs
*
* Creates an pts_pcr_t object
*
* @param tpm_version TPM version
+ * @param algo Hash algorithm used by PCR bank
*/
-pts_pcr_t* pts_pcr_create(tpm_version_t tpm_version);
+pts_pcr_t* pts_pcr_create(tpm_version_t tpm_version, pts_meas_algorithms_t algo);
#endif /** PTS_PCR_H_ @}*/
enumerator_t *(*supported_signature_schemes)(tpm_tss_t *this,
uint32_t handle);
+ /**
+ * Check if there is an assigned PCR bank for the given hash algorithm
+ *
+ * @param alg hash algorithm
+ * @return TRUE if a PCR bank for this algorithm exists
+ */
+ bool (*has_pcr_bank)(tpm_tss_t *this, hash_algorithm_t alg);
+
/**
* Retrieve the current value of a PCR register in a given PCR bank
*
* Get an event digest from a TPM measurement log
*
* @param fd file descriptor of the measurement log
+ * @param hash hash algorithm of the digest to be extracted
* @param digest allocated chunk_t containing event digest
* @return TRUE if event digest was successfully extracted
*/
- bool (*get_event_digest)(tpm_tss_t *this, int fd, chunk_t *digest);
+ bool (*get_event_digest)(tpm_tss_t *this, int fd, hash_algorithm_t alg,
+ chunk_t *digest);
/**
* Destroy a tpm_tss_t.
return enumerator_create_empty();
}
+METHOD(tpm_tss_t, has_pcr_bank, bool,
+ private_tpm_tss_trousers_t *this, hash_algorithm_t alg)
+{
+ return alg == HASH_SHA1;
+}
+
METHOD(tpm_tss_t, read_pcr, bool,
private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
hash_algorithm_t alg)
uint8_t *value;
uint32_t len;
+ if (alg != HASH_SHA1)
+ {
+ return FALSE;
+ }
result = Tspi_TPM_PcrRead(this->hTPM, pcr_num, &len, &value);
if (result != TSS_SUCCESS)
{
uint32_t pcr_len;
uint8_t *pcr_ptr;
+ if (alg != HASH_SHA1)
+ {
+ return FALSE;
+ }
result = Tspi_TPM_PcrExtend(this->hTPM, pcr_num, data.len, data.ptr,
NULL, &pcr_len, &pcr_ptr);
if (result != TSS_SUCCESS)
enumerator_t *enumerator;
bool success = FALSE;
+ if (alg != HASH_SHA1)
+ {
+ return FALSE;
+ }
+
/* Retrieve SRK from TPM and set the authentication to well known secret*/
result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
SRK_UUID, &hSRK);
}
METHOD(tpm_tss_t, get_event_digest, bool,
- private_tpm_tss_trousers_t *this, int fd, chunk_t *digest)
+ private_tpm_tss_trousers_t *this, int fd, hash_algorithm_t alg,
+ chunk_t *digest)
{
+ if (alg != HASH_SHA1)
+ {
+ return FALSE;
+ }
*digest = chunk_alloc(HASH_SIZE_SHA1);
return read(fd, digest->ptr, digest->len) == digest->len;
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
+ .has_pcr_bank = _has_pcr_bank,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
#define LABEL "TPM 2.0 -"
+#define PLATFORM_PCR 24
+#define MAX_PCR_BANKS 4
+
typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
/**
TSS2_SYS_CONTEXT *sys_context;
/**
- * Number of supported algorithms
+ * TPM version info
*/
- size_t supported_algs_count;
+ chunk_t version_info;
/**
- * TPM version info
+ * Number of supported algorithms
*/
- chunk_t version_info;
+ size_t supported_algs_count;
/**
* List of supported algorithms
*/
TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET];
+ /**
+ * Number of assigned PCR banks
+ */
+ size_t assigned_pcrs_count;
+
+ /**
+ * List of assigned PCR banks
+ */
+ TPM_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
+
/**
* Is TPM FIPS 186-4 compliant ?
*/
this->mutex->unlock(this->mutex);
if (rval != TPM_RC_SUCCESS)
{
- DBG1(DBG_PTS, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x",
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_ECC_CURVES: 0x%06x",
LABEL, rval);
return FALSE;
}
}
DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
+ /* get assigned PCR banks */
+ this->mutex->lock(this->mutex);
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_PCRS,
+ 0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
+ this->mutex->unlock(this->mutex);
+ if (rval != TPM_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_PCRS: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+
+ /* Number of assigned PCR banks */
+ this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
+
+ /* reset print buffer */
+ pos = buf;
+ len = BUF_LEN;
+
+ /* store and print assigned PCR banks */
+ for (i = 0; i < cap_data.data.assignedPCR.count; i++)
+ {
+ alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
+ this->assigned_pcrs[i] = alg;
+ written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ DBG2(DBG_PTS, "%s PCR banks:%s", LABEL, buf);
+
return TRUE;
}
(void*)signature_params_destroy);
}
+METHOD(tpm_tss_t, has_pcr_bank, bool,
+ private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
+{
+ TPM_ALG_ID alg_id;
+ int i;
+
+ alg_id = hash_alg_to_tpm_alg_id(alg);
+
+ for (i = 0; i < this->assigned_pcrs_count; i++)
+ {
+ if (this->assigned_pcrs[i] == alg_id)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
* Configure a PCR Selection assuming a maximum of 24 registers
*/
static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
{
- TPM_ALG_ID alg_id;
uint32_t pcr;
- /* check if hash algorithm is supported by TPM */
- alg_id = hash_alg_to_tpm_alg_id(alg);
- if (!is_supported_alg(this, alg_id))
+ /* check if there is an assigned PCR bank for this hash algorithm */
+ if (!has_pcr_bank(this, alg))
{
- DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
LABEL, hash_algorithm_short_names, alg);
return FALSE;
}
/* initialize the PCR Selection structure,*/
pcr_sel->count = 1;
- pcr_sel->pcrSelections[0].hash = alg_id;
+ pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
pcr_sel->pcrSelections[0].sizeofSelect = 3;
pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
chunk_t data, hash_algorithm_t alg)
{
uint32_t rval;
- TPM_ALG_ID alg_id;
TPML_DIGEST_VALUES digest_values;
TPMS_AUTH_COMMAND session_data_cmd;
TPMS_AUTH_RESPONSE session_data_rsp;
*( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
- /* check if hash algorithm is supported by TPM */
- alg_id = hash_alg_to_tpm_alg_id(alg);
- if (!is_supported_alg(this, alg_id))
+ /* check if there is an assigned PCR bank for this hash algorithm */
+ if (!has_pcr_bank(this, alg))
{
- DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
LABEL, hash_algorithm_short_names, alg);
return FALSE;
}
digest_values.count = 1;
- digest_values.digests[0].hashAlg = alg_id;
+ digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
switch (alg)
{
}
METHOD(tpm_tss_t, get_event_digest, bool,
- private_tpm_tss_tss2_t *this, int fd, chunk_t *digest)
+ private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
{
- return FALSE;
+ uint8_t digest_buf[HASH_SIZE_SHA512];
+ uint32_t digest_count;
+ size_t digest_len = 0;
+ hash_algorithm_t hash_alg;
+ TPM_ALG_ID alg_id;
+
+ if (read(fd, &digest_count, 4) != 4)
+ {
+ return FALSE;
+ }
+ while (digest_count--)
+ {
+ if (read(fd, &alg_id, 2) != 2)
+ {
+ return FALSE;
+ }
+ hash_alg = hash_alg_from_tpm_alg_id(alg_id);
+
+ switch (hash_alg)
+ {
+ case HASH_SHA1:
+ digest_len = HASH_SIZE_SHA1;
+ break;
+ case HASH_SHA256:
+ digest_len = HASH_SIZE_SHA256;
+ break;
+ case HASH_SHA384:
+ digest_len = HASH_SIZE_SHA384;
+ break;
+ case HASH_SHA512:
+ digest_len = HASH_SIZE_SHA512;
+ break;
+ default:
+ DBG2(DBG_PTS, "alg_id: 0x%04x", alg_id);
+ return FALSE;
+ }
+ if (hash_alg == alg)
+ {
+ *digest = chunk_alloc(digest_len);
+ if (read(fd, digest->ptr, digest_len) != digest_len)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* read without storing */
+ if (read(fd, digest_buf, digest_len) != digest_len)
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
}
METHOD(tpm_tss_t, destroy, void,
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
+ .has_pcr_bank = _has_pcr_bank,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
#define LABEL "TPM 2.0 -"
#define PLATFORM_PCR 24
+#define MAX_PCR_BANKS 4
typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
TSS2_SYS_CONTEXT *sys_context;
/**
- * Number of supported algorithms
+ * TPM version info
*/
- size_t supported_algs_count;
+ chunk_t version_info;
/**
- * TPM version info
+ * Number of supported algorithms
*/
- chunk_t version_info;
+ size_t supported_algs_count;
/**
* List of supported algorithms
*/
TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
+ /**
+ * Number of assigned PCR banks
+ */
+ size_t assigned_pcrs_count;
+
+ /**
+ * List of assigned PCR banks
+ */
+ TPM2_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
+
/**
* Is TPM FIPS 186-4 compliant ?
*/
this->mutex->unlock(this->mutex);
if (rval != TPM2_RC_SUCCESS)
{
- DBG1(DBG_PTS, "%s GetCapability failed for TPM2_ECC_CURVES: 0x%06x",
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
LABEL, rval);
return FALSE;
}
}
DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
+ /* get assigned PCR banks */
+ this->mutex->lock(this->mutex);
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_PCRS,
+ 0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
+ this->mutex->unlock(this->mutex);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+
+ /* Number of assigned PCR banks */
+ this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
+
+ /* reset print buffer */
+ pos = buf;
+ len = BUF_LEN;
+
+ /* store and print assigned PCR banks */
+ for (i = 0; i < cap_data.data.assignedPCR.count; i++)
+ {
+ alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
+ this->assigned_pcrs[i] = alg;
+ written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ DBG2(DBG_PTS, "%s PCR banks:%s", LABEL, buf);
+
return TRUE;
}
(void*)signature_params_destroy);
}
+METHOD(tpm_tss_t, has_pcr_bank, bool,
+ private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
+{
+ TPM2_ALG_ID alg_id;
+ int i;
+
+ alg_id = hash_alg_to_tpm_alg_id(alg);
+
+ for (i = 0; i < this->assigned_pcrs_count; i++)
+ {
+ if (this->assigned_pcrs[i] == alg_id)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
* Configure a PCR Selection assuming a maximum of 24 registers
*/
static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
{
- TPM2_ALG_ID alg_id;
uint32_t pcr;
- /* check if hash algorithm is supported by TPM */
- alg_id = hash_alg_to_tpm_alg_id(alg);
- if (!is_supported_alg(this, alg_id))
+ /* check if there is an assigned PCR bank for this hash algorithm */
+ if (!has_pcr_bank(this, alg))
{
- DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
LABEL, hash_algorithm_short_names, alg);
return FALSE;
}
/* initialize the PCR Selection structure,*/
pcr_sel->count = 1;
- pcr_sel->pcrSelections[0].hash = alg_id;
+ pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
+;
pcr_sel->pcrSelections[0].sizeofSelect = 3;
pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
chunk_t data, hash_algorithm_t alg)
{
uint32_t rval;
- TPM2_ALG_ID alg_id;
TPML_DIGEST_VALUES digest_values;
TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
TSS2L_SYS_AUTH_RESPONSE auth_rsp;
auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
- /* check if hash algorithm is supported by TPM */
- alg_id = hash_alg_to_tpm_alg_id(alg);
- if (!is_supported_alg(this, alg_id))
+ /* check if there is an assigned PCR bank for this hash algorithm */
+ if (!has_pcr_bank(this, alg))
{
- DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
LABEL, hash_algorithm_short_names, alg);
return FALSE;
}
digest_values.count = 1;
- digest_values.digests[0].hashAlg = alg_id;
+ digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
switch (alg)
{
}
METHOD(tpm_tss_t, get_event_digest, bool,
- private_tpm_tss_tss2_t *this, int fd, chunk_t *digest)
+ private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
{
uint8_t digest_buf[HASH_SIZE_SHA512];
uint32_t digest_count;
DBG2(DBG_PTS, "alg_id: 0x%04x", alg_id);
return FALSE;
}
- if (hash_alg == HASH_SHA1)
+ if (hash_alg == alg)
{
*digest = chunk_alloc(digest_len);
if (read(fd, digest->ptr, digest_len) != digest_len)
}
else
{
- /* currently skip non-SHA1 digests */
+ /* read without storing */
if (read(fd, digest_buf, digest_len) != digest_len)
{
return FALSE;
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
+ .has_pcr_bank = _has_pcr_bank,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,