pts: Variable size PCR banks

This commit is contained in:
Andreas Steffen
2020-10-07 16:54:32 +02:00
parent 56de4dc596
commit 3ef5b23903
17 changed files with 430 additions and 99 deletions
@@ -57,7 +57,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
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);
@@ -85,8 +87,24 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
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)
@@ -146,7 +164,8 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
/* 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;
}
@@ -887,7 +887,7 @@ imv_agent_if_t *imv_attestation_agent_create(const char *name, TNC_IMVID id,
}
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,
@@ -68,7 +68,7 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
}
/* 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))
{
@@ -167,16 +167,14 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
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)
{
@@ -190,7 +188,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
}
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)
{
@@ -362,7 +360,8 @@ METHOD(pts_component_t, measure, status_t,
{
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;
+9 -12
View File
@@ -290,16 +290,10 @@ METHOD(pts_t, calculate_secret, bool,
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;
}
@@ -698,15 +692,18 @@ METHOD(pts_t, quote, bool,
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,
@@ -720,7 +717,7 @@ METHOD(pts_t, quote, bool,
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);
}
@@ -846,7 +843,7 @@ METHOD(pts_t, get_pcrs, pts_pcr_t*,
{
if (!this->pcrs)
{
this->pcrs = pts_pcr_create(this->tpm_version);
this->pcrs = pts_pcr_create(this->tpm_version, this->algorithm);
}
return this->pcrs;
}
@@ -904,8 +901,8 @@ pts_t *pts_create(bool is_imc)
},
.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)
+5 -2
View File
@@ -196,12 +196,14 @@ METHOD(pts_ima_bios_list_t, destroy, void,
/**
* 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;
@@ -228,6 +230,7 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file)
close(fd);
return FALSE;
}
hash_alg = pts_meas_algo_to_hash(algo);
INIT(this,
.public = {
@@ -264,7 +267,7 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file)
{
break;
}
if (!tpm->get_event_digest(tpm, fd, &entry->measurement))
if (!tpm->get_event_digest(tpm, fd, hash_alg, &entry->measurement))
{
break;
}
+6 -1
View File
@@ -21,6 +21,8 @@
#ifndef PTS_IMA_BIOS_LIST_H_
#define PTS_IMA_BIOS_LIST_H_
#include "pts_meas_algo.h"
#include <time.h>
#include <library.h>
@@ -70,7 +72,10 @@ struct pts_ima_bios_list_t {
*
* @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_ @}*/
+63 -11
View File
@@ -19,8 +19,11 @@
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,
@@ -64,9 +67,19 @@ bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
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);
@@ -76,14 +89,14 @@ bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
{
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;
}
@@ -92,33 +105,67 @@ bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
*/
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))
{
@@ -150,6 +197,8 @@ hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm)
return HASH_SHA256;
case PTS_MEAS_ALGO_SHA384:
return HASH_SHA384;
case PTS_MEAS_ALGO_SHA512:
return HASH_SHA512;
default:
return HASH_UNKNOWN;
}
@@ -168,6 +217,8 @@ pts_meas_algorithms_t pts_meas_algo_from_hash(hash_algorithm_t algorithm)
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;
}
@@ -186,9 +237,10 @@ size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm)
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;
}
}
+13
View File
@@ -24,6 +24,7 @@
#include <library.h>
#include <crypto/hashers/hasher.h>
#include <tpm_tss.h>
typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
@@ -32,6 +33,7 @@ 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)
@@ -68,6 +70,8 @@ bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms);
* 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
*
@@ -76,6 +80,15 @@ bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms);
*/
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
+34 -13
View File
@@ -1,5 +1,5 @@
/*
* 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
@@ -52,6 +52,16 @@ struct private_pts_pcr_t {
*/
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
*/
@@ -59,6 +69,12 @@ struct private_pts_pcr_t {
};
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)
{
@@ -162,14 +178,14 @@ METHOD(pts_pcr_t, get, chunk_t,
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;
@@ -178,7 +194,7 @@ METHOD(pts_pcr_t, set, bool,
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;
@@ -206,7 +222,7 @@ METHOD(pts_pcr_t, get_composite, tpm_tss_pcr_composite_t*,
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),
@@ -219,8 +235,8 @@ METHOD(pts_pcr_t, get_composite, tpm_tss_pcr_composite_t*,
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);
@@ -243,22 +259,25 @@ METHOD(pts_pcr_t, destroy, void,
/**
* 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,
@@ -269,13 +288,15 @@ pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version)
.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] */
@@ -285,7 +306,7 @@ pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version)
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;
+11 -6
View File
@@ -23,6 +23,8 @@
typedef struct pts_pcr_t pts_pcr_t;
#include "pts_meas_algo.h"
#include <library.h>
#include <tpm_tss.h>
@@ -33,16 +35,18 @@ typedef struct pts_pcr_t pts_pcr_t;
*/
#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
*
@@ -117,7 +121,8 @@ struct pts_pcr_t {
* 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_ @}*/