sub-component depth from pts database on component evidence request

component hashes are entries in file_hashes table
implemented verify function of tboot component
This commit is contained in:
Sansar Choinyambuu 2011-11-23 11:25:06 +01:00 committed by Andreas Steffen
parent a169fe7793
commit 824a7824dc
13 changed files with 154 additions and 60 deletions

View File

@ -377,7 +377,7 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
"support sub component measurements");
return FALSE;
}
comp = pts_components->create(pts_components, name);
comp = pts_components->create(pts_components, name, depth);
if (!comp)
{
DBG2(DBG_IMC, " not registered: no evidence provided");

View File

@ -176,6 +176,18 @@ INSERT INTO files (
0, '/etc/tnc_config', 1
);
INSERT INTO files (
type, path
) VALUES (
0, 'tboot_pcr17'
);
INSERT INTO files (
type, path
) VALUES (
0, 'tboot_pcr18'
);
/* Components */
INSERT INTO components (
@ -306,6 +318,18 @@ INSERT INTO product_file (
4, 22
);
INSERT INTO product_file (
product, file
) VALUES (
4, 23
);
INSERT INTO product_file (
product, file
) VALUES (
4, 24
);
INSERT INTO product_file (
product, file
) VALUES (
@ -402,30 +426,30 @@ INSERT INTO product_file (
7, 22
);
INSERT INTO product_file (
product, file
) VALUES (
7, 23
);
INSERT INTO product_file (
product, file
) VALUES (
7, 24
);
/* Product Component */
INSERT INTO product_component (
product, component, sequence
product, component, depth, sequence
) VALUES (
4, 1, 1
4, 2, 0, 2
);
INSERT INTO product_component (
product, component, sequence
product, component, depth, sequence
) VALUES (
4, 2, 2
);
INSERT INTO product_component (
product, component, sequence
) VALUES (
7, 1, 1
);
INSERT INTO product_component (
product, component, sequence
) VALUES (
7, 2, 2
7, 2, 0, 2
);
/* File Hashes */
@ -1295,14 +1319,14 @@ INSERT INTO file_hashes (
20, 7, 7, 8192, X'84200bd318bb022915150842ddf4002e061ef593604ad0d07021dc662cc40bfa749cce084ddf25d0e5137f6380f613d8'
);
INSERT INTO component_hashes (
component, product, algo, hash
INSERT INTO file_hashes (
file, product, component, algo, hash
) VALUES (
2, 4, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902'
23, 4, 2, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902'
);
INSERT INTO component_hashes (
component, product, algo, hash
INSERT INTO file_hashes (
file, product, component, algo, hash
) VALUES (
2, 4, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0'
24, 4, 2, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0'
);

View File

@ -215,6 +215,7 @@ bool imv_attestation_build(pa_tnc_msg_t *msg,
pts_comp_func_name_t *comp_name;
int vid, name, qualifier;
u_int8_t flags;
u_int32_t depth;
bool first = TRUE;
attestation_state->set_handshake_state(attestation_state,
@ -237,12 +238,13 @@ bool imv_attestation_build(pa_tnc_msg_t *msg,
break;
}
DBG2(DBG_IMV, "evidence request by");
while (enumerator->enumerate(enumerator, &vid, &name, &qualifier))
while (enumerator->enumerate(enumerator, &vid, &name,
&qualifier, &depth))
{
comp_name = pts_comp_func_name_create(vid, name, qualifier);
comp_name->log(comp_name, " ");
comp = pts_components->create(pts_components, comp_name);
comp = pts_components->create(pts_components, comp_name, depth);
if (!comp)
{
DBG2(DBG_IMV, " not registered: removed from request");
@ -259,7 +261,7 @@ bool imv_attestation_build(pa_tnc_msg_t *msg,
flags = comp->get_evidence_flags(comp);
/* TODO check flags against negotiated_caps */
attr_cast = (tcg_pts_attr_req_func_comp_evid_t *)attr;
attr_cast->add_component(attr_cast, flags, 0, comp_name);
attr_cast->add_component(attr_cast, flags, depth, comp_name);
}
enumerator->destroy(enumerator);

View File

@ -38,6 +38,7 @@ DROP TABLE IF EXISTS product_component;
CREATE TABLE product_component (
product INTEGER NOT NULL,
component INTEGER NOT NULL,
depth INTEGER DEFAULT 0,
sequence INTEGER DEFAULT 0,
PRIMARY KEY (product, component)
);
@ -47,17 +48,8 @@ CREATE TABLE file_hashes (
file INTEGER NOT NULL,
directory INTEGER DEFAULT 0,
product INTEGER NOT NULL,
component INTEGER DEFAULT 0,
algo INTEGER NOT NULL,
hash BLOB NOT NULL,
PRIMARY KEY(file, directory, product, algo)
PRIMARY KEY(file, directory, product, component, algo)
);
DROP TABLE IF EXISTS component_hashes;
CREATE TABLE component_hashes (
component INTEGER NOT NULL,
product INTEGER NOT NULL,
algo INTEGER NOT NULL,
hash BLOB NOT NULL,
PRIMARY KEY(component, product, algo)
);

View File

@ -40,6 +40,11 @@ struct pts_ita_comp_tboot_t {
*/
pts_comp_func_name_t *name;
/**
* Sub-component depth
*/
u_int32_t depth;
/**
* Extended PCR last handled
*/
@ -64,6 +69,12 @@ METHOD(pts_component_t, get_evidence_flags, u_int8_t,
return PTS_REQ_FUNC_COMP_EVID_PCR;
}
METHOD(pts_component_t, get_depth, u_int32_t,
pts_ita_comp_tboot_t *this)
{
return this->depth;
}
METHOD(pts_component_t, measure, status_t,
pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
{
@ -124,27 +135,62 @@ METHOD(pts_component_t, verify, status_t,
pts_pcr_transform_t transform;
time_t measurement_time;
chunk_t measurement, pcr_before, pcr_after;
enumerator_t *enumerator;
char *file;
chunk_t hash;
char *platform_info;
platform_info = pts->get_platform_info(pts);
if (!pts_db || !platform_info)
{
DBG1(DBG_PTS, "%s%s%s not available",
(pts_db) ? "" : "pts database",
(!pts_db && !platform_info) ? "and" : "",
(platform_info) ? "" : "platform info");
return FAILED;
}
switch (this->extended_pcr)
{
case 0:
this->extended_pcr = PCR_TBOOT_POLICY;
file = "tboot_pcr17";
break;
case PCR_TBOOT_POLICY:
this->extended_pcr = PCR_TBOOT_MLE;
file = "tboot_pcr18";
break;
default:
return FAILED;
}
measurement = evidence->get_measurement(evidence, &extended_pcr,
&algo, &transform, &measurement_time);
&algo, &transform, &measurement_time);
if (extended_pcr != this->extended_pcr)
{
return FAILED;
}
/* TODO check measurement in database */
/* check measurement in database */
enumerator = pts_db->create_comp_hash_enumerator(pts_db, file,
platform_info, this->name, algo);
while (enumerator->enumerate(enumerator, &hash))
{
if (!chunk_equals(hash, measurement))
{
DBG1(DBG_PTS, "Incorrect TBOOT component measurement for PCR %d. "
"Expected: %#B, Received: %#B",
this->extended_pcr, &hash, &measurement);
return FAILED;
}
else
{
DBG3(DBG_PTS, "Matching TBOOT component measurement for PCR %d",
this->extended_pcr);
break;
}
}
enumerator->destroy(enumerator);
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
if (has_pcr_info)
@ -159,7 +205,7 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, destroy, void,
pts_ita_comp_tboot_t *this)
pts_ita_comp_tboot_t *this)
{
this->name->destroy(this->name);
free(this);
@ -168,7 +214,7 @@ METHOD(pts_component_t, destroy, void,
/**
* See header
*/
pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier)
pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth)
{
pts_ita_comp_tboot_t *this;
@ -176,12 +222,14 @@ pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier)
.public = {
.get_comp_func_name = _get_comp_func_name,
.get_evidence_flags = _get_evidence_flags,
.get_depth = _get_depth,
.measure = _measure,
.verify = _verify,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
qualifier),
.depth = depth,
);
return &this->public;

View File

@ -29,6 +29,6 @@
* @param qualifier PTS Component Functional Name Qualifier
*
*/
pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier);
pts_component_t* pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth);
#endif /** PTS_ITA_COMP_TBOOT_H_ @}*/

View File

@ -39,6 +39,11 @@ struct pts_ita_comp_tgrub_t {
* Component Functional Name
*/
pts_comp_func_name_t *name;
/**
* Sub-component depth
*/
u_int32_t depth;
};
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
@ -53,6 +58,12 @@ METHOD(pts_component_t, get_evidence_flags, u_int8_t,
return PTS_REQ_FUNC_COMP_EVID_PCR;
}
METHOD(pts_component_t, get_depth, u_int32_t,
pts_ita_comp_tgrub_t *this)
{
return this->depth;
}
METHOD(pts_component_t, measure, status_t,
pts_ita_comp_tgrub_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
{
@ -128,7 +139,7 @@ METHOD(pts_component_t, destroy, void,
/**
* See header
*/
pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier)
pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth)
{
pts_ita_comp_tgrub_t *this;
@ -136,12 +147,14 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int8_t qualifier)
.public = {
.get_comp_func_name = _get_comp_func_name,
.get_evidence_flags = _get_evidence_flags,
.get_depth = _get_depth,
.measure = _measure,
.verify = _verify,
.destroy = _destroy,
},
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
qualifier),
.depth = depth,
);
return &this->public;

View File

@ -29,6 +29,6 @@
* @param qualifier PTS Component Functional Name Qualifier
*
*/
pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier);
pts_component_t* pts_ita_comp_tgrub_create(u_int8_t qualifier, u_int32_t depth);
#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/

View File

@ -49,6 +49,13 @@ struct pts_component_t {
*/
u_int8_t (*get_evidence_flags)(pts_component_t *this);
/**
* Get the PTS Sub-component Depth
*
* @return PTS Sub-component Depth
*/
u_int32_t (*get_depth)(pts_component_t *this);
/**
* Do evidence measurements on the PTS Functional Component
*

View File

@ -252,7 +252,8 @@ METHOD(pts_component_manager_t, get_qualifier, u_int8_t,
}
METHOD(pts_component_manager_t, create, pts_component_t*,
private_pts_component_manager_t *this, pts_comp_func_name_t *name)
private_pts_component_manager_t *this,
pts_comp_func_name_t *name, u_int32_t depth)
{
enumerator_t *enumerator, *e2;
vendor_entry_t *entry;
@ -269,7 +270,7 @@ METHOD(pts_component_manager_t, create, pts_component_t*,
{
if (entry2->name == name->get_name(name) && entry2->create)
{
component = entry2->create(name->get_qualifier(name));
component = entry2->create(name->get_qualifier(name), depth);
break;
}
}

View File

@ -29,7 +29,8 @@ typedef struct pts_component_manager_t pts_component_manager_t;
#include <library.h>
#include <pen/pen.h>
typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier);
typedef pts_component_t* (*pts_component_create_t)(u_int8_t qualifier,
u_int32_t depth);
/**
* Manages PTS Functional Components
@ -100,10 +101,11 @@ struct pts_component_manager_t {
* Create a PTS Component object from a Functional Component Name object
*
* @param name Component Functional Name
* @param depth Sub-component Depth
* @return Component object if supported, NULL else
*/
pts_component_t* (*create)(pts_component_manager_t *this,
pts_comp_func_name_t *name);
pts_comp_func_name_t *name, u_int32_t depth);
/**
* Destroys a pts_component_manager_t object.

View File

@ -76,11 +76,12 @@ METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
/* look for all entries belonging to a product in the components table */
e = this->db->query(this->db,
"SELECT c.vendor_id, c.name, c.qualifier FROM components AS c "
"SELECT c.vendor_id, c.name, c.qualifier, pc.depth "
"FROM components AS c "
"JOIN product_component AS pc ON c.id = pc.component "
"JOIN products AS p ON p.id = pc.product "
"WHERE p.name = ? ORDER BY pc.sequence",
DB_TEXT, product, DB_INT, DB_INT, DB_INT);
DB_TEXT, product, DB_INT, DB_INT, DB_INT, DB_INT);
return e;
}
@ -114,18 +115,20 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
}
METHOD(pts_database_t, create_comp_hash_enumerator, enumerator_t*,
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
pts_comp_func_name_t *comp_name)
private_pts_database_t *this, char *file, char *product,
pts_comp_func_name_t *comp_name, pts_meas_algorithms_t algo)
{
enumerator_t *e;
e = this->db->query(this->db,
"SELECT ch.hash FROM component_hashes AS ch "
"JOIN components AS c ON ch.component = c.id "
"JOIN products AS p ON ch.product = p.id "
"WHERE p.name = ? AND c.vendor_id = ? "
"AND c.name = ? AND c.qualifier = ? AND ch.algo = ? ",
DB_TEXT, product, DB_INT, comp_name->get_vendor_id(comp_name),
"SELECT fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON fh.file = f.id "
"JOIN products AS p ON fh.product = p.id "
"JOIN components AS c ON fh.component = c.id "
"WHERE f.path = ? AND p.name = ? AND c.vendor_id = ? "
"AND c.name = ? AND c.qualifier = ? AND fh.algo = ? ",
DB_TEXT, file, DB_TEXT, product,
DB_INT, comp_name->get_vendor_id(comp_name),
DB_INT, comp_name->get_name(comp_name),
DB_INT, comp_name->get_qualifier(comp_name),
DB_INT, algo, DB_BLOB);

View File

@ -76,14 +76,16 @@ struct pts_database_t {
/**
* Get stored measurement hash for functional component entries
*
* @param file file path in files table
* @param product software product (os, vpn client, etc.)
* @param algo hash algorithm used for measurement
* @param comp_name functional component name object
* @return enumerator over all matching measurement hashes
*/
enumerator_t* (*create_comp_hash_enumerator)(pts_database_t *this,
char *product, pts_meas_algorithms_t algo,
pts_comp_func_name_t *comp_name);
char *file, char *product,
pts_comp_func_name_t *comp_name,
pts_meas_algorithms_t algo);
/**
* Destroys a pts_database_t object.