bound functional component measurements to AIK
This commit is contained in:
@@ -97,10 +97,12 @@ static void do_args(int argc, char *argv[])
|
|||||||
enum {
|
enum {
|
||||||
OP_UNDEF,
|
OP_UNDEF,
|
||||||
OP_USAGE,
|
OP_USAGE,
|
||||||
OP_FILES,
|
OP_KEYS,
|
||||||
OP_COMPONENTS,
|
OP_COMPONENTS,
|
||||||
OP_PRODUCTS,
|
OP_FILES,
|
||||||
OP_HASHES,
|
OP_HASHES,
|
||||||
|
OP_MEASUREMENTS,
|
||||||
|
OP_PRODUCTS,
|
||||||
OP_ADD,
|
OP_ADD,
|
||||||
OP_DEL,
|
OP_DEL,
|
||||||
} op = OP_UNDEF;
|
} op = OP_UNDEF;
|
||||||
@@ -116,8 +118,10 @@ static void do_args(int argc, char *argv[])
|
|||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "components", no_argument, NULL, 'c' },
|
{ "components", no_argument, NULL, 'c' },
|
||||||
{ "files", no_argument, NULL, 'f' },
|
{ "files", no_argument, NULL, 'f' },
|
||||||
|
{ "keys", no_argument, NULL, 'k' },
|
||||||
{ "products", no_argument, NULL, 'p' },
|
{ "products", no_argument, NULL, 'p' },
|
||||||
{ "hashes", no_argument, NULL, 'H' },
|
{ "hashes", no_argument, NULL, 'H' },
|
||||||
|
{ "measurements", no_argument, NULL, 'M' },
|
||||||
{ "add", no_argument, NULL, 'a' },
|
{ "add", no_argument, NULL, 'a' },
|
||||||
{ "delete", no_argument, NULL, 'd' },
|
{ "delete", no_argument, NULL, 'd' },
|
||||||
{ "del", no_argument, NULL, 'd' },
|
{ "del", no_argument, NULL, 'd' },
|
||||||
@@ -129,6 +133,8 @@ static void do_args(int argc, char *argv[])
|
|||||||
{ "directory", required_argument, NULL, 'D' },
|
{ "directory", required_argument, NULL, 'D' },
|
||||||
{ "dir", required_argument, NULL, 'D' },
|
{ "dir", required_argument, NULL, 'D' },
|
||||||
{ "file", required_argument, NULL, 'F' },
|
{ "file", required_argument, NULL, 'F' },
|
||||||
|
{ "key", required_argument, NULL, 'K' },
|
||||||
|
{ "owner", required_argument, NULL, 'O' },
|
||||||
{ "product", required_argument, NULL, 'P' },
|
{ "product", required_argument, NULL, 'P' },
|
||||||
{ "sha1", no_argument, NULL, '1' },
|
{ "sha1", no_argument, NULL, '1' },
|
||||||
{ "sha256", no_argument, NULL, '2' },
|
{ "sha256", no_argument, NULL, '2' },
|
||||||
@@ -137,6 +143,7 @@ static void do_args(int argc, char *argv[])
|
|||||||
{ "fid", required_argument, NULL, '5' },
|
{ "fid", required_argument, NULL, '5' },
|
||||||
{ "pid", required_argument, NULL, '6' },
|
{ "pid", required_argument, NULL, '6' },
|
||||||
{ "cid", required_argument, NULL, '7' },
|
{ "cid", required_argument, NULL, '7' },
|
||||||
|
{ "kid", required_argument, NULL, '8' },
|
||||||
{ 0,0,0,0 }
|
{ 0,0,0,0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -154,12 +161,18 @@ static void do_args(int argc, char *argv[])
|
|||||||
case 'f':
|
case 'f':
|
||||||
op = OP_FILES;
|
op = OP_FILES;
|
||||||
continue;
|
continue;
|
||||||
|
case 'k':
|
||||||
|
op = OP_KEYS;
|
||||||
|
continue;
|
||||||
case 'p':
|
case 'p':
|
||||||
op = OP_PRODUCTS;
|
op = OP_PRODUCTS;
|
||||||
continue;
|
continue;
|
||||||
case 'H':
|
case 'H':
|
||||||
op = OP_HASHES;
|
op = OP_HASHES;
|
||||||
continue;
|
continue;
|
||||||
|
case 'M':
|
||||||
|
op = OP_MEASUREMENTS;
|
||||||
|
continue;
|
||||||
case 'a':
|
case 'a':
|
||||||
op = OP_ADD;
|
op = OP_ADD;
|
||||||
continue;
|
continue;
|
||||||
@@ -199,6 +212,15 @@ static void do_args(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
case 'K':
|
||||||
|
if (!attest->set_key(attest, optarg, op == OP_ADD))
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 'O':
|
||||||
|
attest->set_owner(attest, optarg);
|
||||||
|
continue;
|
||||||
case 'P':
|
case 'P':
|
||||||
if (!attest->set_product(attest, optarg, op == OP_ADD))
|
if (!attest->set_product(attest, optarg, op == OP_ADD))
|
||||||
{
|
{
|
||||||
@@ -238,6 +260,12 @@ static void do_args(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
case '8':
|
||||||
|
if (!attest->set_kid(attest, atoi(optarg)))
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -250,6 +278,9 @@ static void do_args(int argc, char *argv[])
|
|||||||
case OP_PRODUCTS:
|
case OP_PRODUCTS:
|
||||||
attest->list_products(attest);
|
attest->list_products(attest);
|
||||||
break;
|
break;
|
||||||
|
case OP_KEYS:
|
||||||
|
attest->list_keys(attest);
|
||||||
|
break;
|
||||||
case OP_COMPONENTS:
|
case OP_COMPONENTS:
|
||||||
attest->list_components(attest);
|
attest->list_components(attest);
|
||||||
break;
|
break;
|
||||||
@@ -259,6 +290,9 @@ static void do_args(int argc, char *argv[])
|
|||||||
case OP_HASHES:
|
case OP_HASHES:
|
||||||
attest->list_hashes(attest);
|
attest->list_hashes(attest);
|
||||||
break;
|
break;
|
||||||
|
case OP_MEASUREMENTS:
|
||||||
|
attest->list_measurements(attest);
|
||||||
|
break;
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
attest->add(attest);
|
attest->add(attest);
|
||||||
break;
|
break;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -33,40 +33,6 @@ typedef struct attest_db_t attest_db_t;
|
|||||||
*/
|
*/
|
||||||
struct attest_db_t {
|
struct attest_db_t {
|
||||||
|
|
||||||
/**
|
|
||||||
* Set software product to be queried
|
|
||||||
*
|
|
||||||
* @param product software product
|
|
||||||
* @param create if TRUE create database entry if it doesn't exist
|
|
||||||
* @return TRUE if successful
|
|
||||||
*/
|
|
||||||
bool (*set_product)(attest_db_t *this, char *product, bool create);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set primary key of the software product to be queried
|
|
||||||
*
|
|
||||||
* @param pid primary key of software product
|
|
||||||
* @return TRUE if successful
|
|
||||||
*/
|
|
||||||
bool (*set_pid)(attest_db_t *this, int pid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set measurement file to be queried
|
|
||||||
*
|
|
||||||
* @param file measurement file
|
|
||||||
* @param create if TRUE create database entry if it doesn't exist
|
|
||||||
* @return TRUE if successful
|
|
||||||
*/
|
|
||||||
bool (*set_file)(attest_db_t *this, char *file, bool create);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set primary key of the measurement file to be queried
|
|
||||||
*
|
|
||||||
* @param fid primary key of measurement file
|
|
||||||
* @return TRUE if successful
|
|
||||||
*/
|
|
||||||
bool (*set_fid)(attest_db_t *this, int fid);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set functional component to be queried
|
* Set functional component to be queried
|
||||||
*
|
*
|
||||||
@@ -101,6 +67,57 @@ struct attest_db_t {
|
|||||||
*/
|
*/
|
||||||
bool (*set_did)(attest_db_t *this, int did);
|
bool (*set_did)(attest_db_t *this, int did);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set measurement file to be queried
|
||||||
|
*
|
||||||
|
* @param file measurement file
|
||||||
|
* @param create if TRUE create database entry if it doesn't exist
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_file)(attest_db_t *this, char *file, bool create);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set primary key of the measurement file to be queried
|
||||||
|
*
|
||||||
|
* @param fid primary key of measurement file
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_fid)(attest_db_t *this, int fid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set functional component to be queried
|
||||||
|
*
|
||||||
|
* @param key AIK
|
||||||
|
* @param create if TRUE create database entry if it doesn't exist
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_key)(attest_db_t *this, char *key, bool create);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set primary key of the AIK to be queried
|
||||||
|
*
|
||||||
|
* @param kid primary key of AIK
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_kid)(attest_db_t *this, int kid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set software product to be queried
|
||||||
|
*
|
||||||
|
* @param product software product
|
||||||
|
* @param create if TRUE create database entry if it doesn't exist
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_product)(attest_db_t *this, char *product, bool create);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set primary key of the software product to be queried
|
||||||
|
*
|
||||||
|
* @param pid primary key of software product
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
bool (*set_pid)(attest_db_t *this, int pid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set measurement hash algorithm
|
* Set measurement hash algorithm
|
||||||
*
|
*
|
||||||
@@ -108,6 +125,14 @@ struct attest_db_t {
|
|||||||
*/
|
*/
|
||||||
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
|
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set owner [user/host] of an AIK
|
||||||
|
*
|
||||||
|
* @param owner user/host name
|
||||||
|
* @return TRUE if successful
|
||||||
|
*/
|
||||||
|
void (*set_owner)(attest_db_t *this, char *owner);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all products stored in the database
|
* List all products stored in the database
|
||||||
*/
|
*/
|
||||||
@@ -123,11 +148,21 @@ struct attest_db_t {
|
|||||||
*/
|
*/
|
||||||
void (*list_components)(attest_db_t *this);
|
void (*list_components)(attest_db_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all AIKs stored in the database
|
||||||
|
*/
|
||||||
|
void (*list_keys)(attest_db_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List selected measurement hashes stored in the database
|
* List selected measurement hashes stored in the database
|
||||||
*/
|
*/
|
||||||
void (*list_hashes)(attest_db_t *this);
|
void (*list_hashes)(attest_db_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List selected component measurement stored in the database
|
||||||
|
*/
|
||||||
|
void (*list_measurements)(attest_db_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an entry to the database
|
* Add an entry to the database
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,16 +24,14 @@ void usage(void)
|
|||||||
{
|
{
|
||||||
printf("\
|
printf("\
|
||||||
Usage:\n\
|
Usage:\n\
|
||||||
ipsec attest --files|--components|--products|--hashes|--add|--del [options]\n\
|
ipsec attest --files|--products|--keys|--hashes [options]\n\
|
||||||
|
\n\
|
||||||
|
ipsec attest --components|-keys|--measurements|--add|--del [options]\n\
|
||||||
\n\
|
\n\
|
||||||
ipsec attest --files [--product <name>|--pid <id>]\n\
|
ipsec attest --files [--product <name>|--pid <id>]\n\
|
||||||
Show a list of files with a software product name or\n\
|
Show a list of files with a software product name or\n\
|
||||||
its primary key as an optional selector.\n\
|
its primary key as an optional selector.\n\
|
||||||
\n\
|
\n\
|
||||||
ipsec attest --components [--product <name>|--pid <id>]\n\
|
|
||||||
Show a list of components with a software product name or\n\
|
|
||||||
its primary key as an optional selector.\n\
|
|
||||||
\n\
|
|
||||||
ipsec attest --products [--file <path>|--fid <id>]\n\
|
ipsec attest --products [--file <path>|--fid <id>]\n\
|
||||||
Show a list of supported software products with a file path or\n\
|
Show a list of supported software products with a file path or\n\
|
||||||
its primary key as an optional selector.\n\
|
its primary key as an optional selector.\n\
|
||||||
@@ -46,15 +44,37 @@ Usage:\n\
|
|||||||
Show a list of measurement hashes for a given file or\n\
|
Show a list of measurement hashes for a given file or\n\
|
||||||
its primary key as an optional selector.\n\
|
its primary key as an optional selector.\n\
|
||||||
\n\
|
\n\
|
||||||
|
ipsec attest --components [--key <digest>|--kid <id>]\n\
|
||||||
|
Show a list of components with an AIK digest or\n\
|
||||||
|
its primary key as an optional selector.\n\
|
||||||
|
\n\
|
||||||
|
ipsec attest --keys [--components <cfn>|--cid <id>]\n\
|
||||||
|
Show a list of AIK key digests with a component or\n\
|
||||||
|
its primary key as an optional selector.\n\
|
||||||
|
\n\
|
||||||
|
ipsec attest --measurements [--sha1|--sha256|--sha384] [--component <cfn>|--cid <id>]\n\
|
||||||
|
Show a list of component measurements for a given component or\n\
|
||||||
|
its primary key as an optional selector.\n\
|
||||||
|
\n\
|
||||||
|
ipsec attest --measurements [--sha1|--sha256|--sha384] [--key <digest>|--kid <id>]\n\
|
||||||
|
Show a list of component measurements for a given AIK or\n\
|
||||||
|
its primary key as an optional selector.\n\
|
||||||
|
\n\
|
||||||
ipsec attest --add --file <path>|--dir <path>|--product <name>|--component <cfn>\n\
|
ipsec attest --add --file <path>|--dir <path>|--product <name>|--component <cfn>\n\
|
||||||
Add a file, directory, product or component entry\n\
|
Add a file, directory, product or component entry\n\
|
||||||
Component <cfn> entries must be of the form <vendor_id>/<name>-<qualifier>\n\
|
Component <cfn> entries must be of the form <vendor_id>/<name>-<qualifier>\n\
|
||||||
\n\
|
\n\
|
||||||
|
ipsec attest --add [--owner <name>] --key <digest>\n\
|
||||||
|
Add an AIK public key digest entry preceded by an optional owner name\n\
|
||||||
|
\n\
|
||||||
ipsec attest --del --file <path>|--fid <id>|--dir <path>|--did <id>\n\
|
ipsec attest --del --file <path>|--fid <id>|--dir <path>|--did <id>\n\
|
||||||
Delete a file or directoryentry referenced either by value or primary key\n\
|
Delete a file or directory entry referenced either by value or primary key\n\
|
||||||
\n\
|
\n\
|
||||||
ipsec attest --del --product <name>|--pid <id>|--component <cfn>|--cid <id>\n\
|
ipsec attest --del --product <name>|--pid <id>|--component <cfn>|--cid <id>\n\
|
||||||
Delete a product or component entry referenced either by value or primary key\n\
|
Delete a product or component entry referenced either by value or primary key\n\
|
||||||
|
\n\
|
||||||
|
ipsec attest --del --key <digest>|--kid <id>\n\
|
||||||
|
Delete an AIK entry referenced either by value or primary key\n\
|
||||||
\n");
|
\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -210,9 +210,9 @@ bool imv_attestation_build(pa_tnc_msg_t *msg,
|
|||||||
{
|
{
|
||||||
tcg_pts_attr_req_func_comp_evid_t *attr_cast;
|
tcg_pts_attr_req_func_comp_evid_t *attr_cast;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
char *platform_info;
|
|
||||||
pts_component_t *comp;
|
pts_component_t *comp;
|
||||||
pts_comp_func_name_t *comp_name;
|
pts_comp_func_name_t *comp_name;
|
||||||
|
chunk_t keyid;
|
||||||
int vid, name, qualifier;
|
int vid, name, qualifier;
|
||||||
u_int8_t flags;
|
u_int8_t flags;
|
||||||
u_int32_t depth;
|
u_int32_t depth;
|
||||||
@@ -221,18 +221,17 @@ bool imv_attestation_build(pa_tnc_msg_t *msg,
|
|||||||
attestation_state->set_handshake_state(attestation_state,
|
attestation_state->set_handshake_state(attestation_state,
|
||||||
IMV_ATTESTATION_STATE_END);
|
IMV_ATTESTATION_STATE_END);
|
||||||
|
|
||||||
/* Get Platform and OS of the PTS-IMC */
|
if (!pts->get_aik_keyid(pts, &keyid))
|
||||||
platform_info = pts->get_platform_info(pts);
|
|
||||||
if (!pts_db || !platform_info)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMV, "%s%s%s not available",
|
break;
|
||||||
(pts_db) ? "" : "pts database",
|
}
|
||||||
(!pts_db && !platform_info) ? "and" : "",
|
if (!pts_db)
|
||||||
(platform_info) ? "" : "platform info");
|
{
|
||||||
|
DBG1(DBG_PTS, "pts database not available");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerator = pts_db->create_comp_evid_enumerator(pts_db, platform_info);
|
enumerator = pts_db->create_comp_evid_enumerator(pts_db, keyid);
|
||||||
if (!enumerator)
|
if (!enumerator)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
{
|
{
|
||||||
tcg_pts_attr_aik_t *attr_cast;
|
tcg_pts_attr_aik_t *attr_cast;
|
||||||
certificate_t *aik, *issuer;
|
certificate_t *aik, *issuer;
|
||||||
|
public_key_t *public;
|
||||||
|
chunk_t keyid;
|
||||||
enumerator_t *e;
|
enumerator_t *e;
|
||||||
bool trusted = FALSE;
|
bool trusted = FALSE;
|
||||||
|
|
||||||
@@ -158,7 +160,11 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
}
|
}
|
||||||
if (aik->get_type(aik) == CERT_X509)
|
if (aik->get_type(aik) == CERT_X509)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMV, "verifying AIK certificate");
|
public = aik->get_public_key(aik);
|
||||||
|
public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
|
||||||
|
DBG1(DBG_IMV, "verifying AIK certificate with keyid %#B", &keyid);
|
||||||
|
public->destroy(public);
|
||||||
|
|
||||||
e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
|
e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
|
||||||
KEY_ANY, aik->get_issuer(aik), FALSE);
|
KEY_ANY, aik->get_issuer(aik), FALSE);
|
||||||
while (e->enumerate(e, &issuer))
|
while (e->enumerate(e, &issuer))
|
||||||
@@ -285,8 +291,10 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
|
|||||||
default:
|
default:
|
||||||
case FAILED:
|
case FAILED:
|
||||||
attestation_state->set_measurement_error(attestation_state);
|
attestation_state->set_measurement_error(attestation_state);
|
||||||
/* fall through to next case */
|
comp->destroy(comp);
|
||||||
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
|
name->log(name, " successfully measured ");
|
||||||
comp->destroy(comp);
|
comp->destroy(comp);
|
||||||
break;
|
break;
|
||||||
case NEED_MORE:
|
case NEED_MORE:
|
||||||
|
|||||||
@@ -7,14 +7,6 @@ CREATE TABLE files (
|
|||||||
path TEXT NOT NULL
|
path TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
DROP TABLE IF EXISTS components;
|
|
||||||
CREATE TABLE components (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
vendor_id INTEGER NOT NULL,
|
|
||||||
name INTEGER NOT NULL,
|
|
||||||
qualifier INTEGER DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS products;
|
DROP TABLE IF EXISTS products;
|
||||||
CREATE TABLE products (
|
CREATE TABLE products (
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -34,15 +26,6 @@ CREATE TABLE product_file (
|
|||||||
PRIMARY KEY (product, file)
|
PRIMARY KEY (product, file)
|
||||||
);
|
);
|
||||||
|
|
||||||
DROP TABLE IF EXISTS product_component;
|
|
||||||
CREATE TABLE product_component (
|
|
||||||
product INTEGER NOT NULL,
|
|
||||||
component INTEGER NOT NULL,
|
|
||||||
depth INTEGER DEFAULT 0,
|
|
||||||
seq_no INTEGER DEFAULT 0,
|
|
||||||
PRIMARY KEY (product, component)
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS file_hashes;
|
DROP TABLE IF EXISTS file_hashes;
|
||||||
CREATE TABLE file_hashes (
|
CREATE TABLE file_hashes (
|
||||||
file INTEGER NOT NULL,
|
file INTEGER NOT NULL,
|
||||||
@@ -53,13 +36,47 @@ CREATE TABLE file_hashes (
|
|||||||
PRIMARY KEY(file, directory, product, algo)
|
PRIMARY KEY(file, directory, product, algo)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS keys;
|
||||||
|
CREATE TABLE keys (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
keyid BLOB NOT NULL,
|
||||||
|
owner TEXT NOT NULL
|
||||||
|
);
|
||||||
|
DROP INDEX IF EXISTS keys_keyid;
|
||||||
|
CREATE INDEX keys_keyid ON keys (
|
||||||
|
keyid
|
||||||
|
);
|
||||||
|
DROP INDEX IF EXISTS keys_owner;
|
||||||
|
CREATE INDEX keys_owner ON keys (
|
||||||
|
owner
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS components;
|
||||||
|
CREATE TABLE components (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
vendor_id INTEGER NOT NULL,
|
||||||
|
name INTEGER NOT NULL,
|
||||||
|
qualifier INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS key_component;
|
||||||
|
CREATE TABLE key_component (
|
||||||
|
key INTEGER NOT NULL,
|
||||||
|
component INTEGER NOT NULL,
|
||||||
|
depth INTEGER DEFAULT 0,
|
||||||
|
seq_no INTEGER DEFAULT 0,
|
||||||
|
PRIMARY KEY (key, component)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS component_hashes;
|
DROP TABLE IF EXISTS component_hashes;
|
||||||
CREATE TABLE component_hashes (
|
CREATE TABLE component_hashes (
|
||||||
component INTEGER NOT NULL,
|
component INTEGER NOT NULL,
|
||||||
product INTEGER NOT NULL,
|
key INTEGER NOT NULL,
|
||||||
seq_no INTEGER NOT NULL,
|
seq_no INTEGER NOT NULL,
|
||||||
pcr INTEGER NOT NULL,
|
pcr INTEGER NOT NULL,
|
||||||
algo INTEGER NOT NULL,
|
algo INTEGER NOT NULL,
|
||||||
hash BLOB NOT NULL,
|
hash BLOB NOT NULL,
|
||||||
PRIMARY KEY(component, product, seq_no, algo)
|
PRIMARY KEY(component, key, seq_no, algo)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "ita_comp_ima.h"
|
#include "ita_comp_ima.h"
|
||||||
#include "ita_comp_func_name.h"
|
#include "ita_comp_func_name.h"
|
||||||
|
|
||||||
|
#include "libpts.h"
|
||||||
#include "pts/components/pts_component.h"
|
#include "pts/components/pts_component.h"
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -31,7 +32,6 @@
|
|||||||
#define IMA_SECURITY_DIR "/sys/kernel/security/tpm0/"
|
#define IMA_SECURITY_DIR "/sys/kernel/security/tpm0/"
|
||||||
#define IMA_BIOS_MEASUREMENT_PATH IMA_SECURITY_DIR "binary_bios_measurements"
|
#define IMA_BIOS_MEASUREMENT_PATH IMA_SECURITY_DIR "binary_bios_measurements"
|
||||||
#define IMA_PCR_MAX 8
|
#define IMA_PCR_MAX 8
|
||||||
#define IMA_SEQUENCE 126
|
|
||||||
|
|
||||||
typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
|
typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
|
||||||
|
|
||||||
@@ -56,6 +56,11 @@ struct pts_ita_comp_ima_t {
|
|||||||
*/
|
*/
|
||||||
u_int32_t depth;
|
u_int32_t depth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIK keyid
|
||||||
|
*/
|
||||||
|
chunk_t keyid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMA BIOS measurement time
|
* IMA BIOS measurement time
|
||||||
*/
|
*/
|
||||||
@@ -66,6 +71,11 @@ struct pts_ita_comp_ima_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *list;
|
linked_list_t *list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected measurement count
|
||||||
|
*/
|
||||||
|
int count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measurement sequence number
|
* Measurement sequence number
|
||||||
*/
|
*/
|
||||||
@@ -247,27 +257,50 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
pts_comp_evidence_t *evidence)
|
pts_comp_evidence_t *evidence)
|
||||||
{
|
{
|
||||||
bool has_pcr_info;
|
bool has_pcr_info;
|
||||||
char *platform_info;
|
u_int32_t extended_pcr, vid, name;
|
||||||
u_int32_t extended_pcr;
|
enum_name_t *names;
|
||||||
pts_meas_algorithms_t algo;
|
pts_meas_algorithms_t algo;
|
||||||
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;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
||||||
&algo, &transform, &measurement_time);
|
&algo, &transform, &measurement_time);
|
||||||
|
|
||||||
|
if (!this->keyid.ptr)
|
||||||
|
{
|
||||||
|
if (!pts->get_aik_keyid(pts, &this->keyid))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
this->keyid = chunk_clone(this->keyid);
|
||||||
|
|
||||||
|
if (!pts_db)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "pts database not available");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!pts_db->get_comp_measurement_count(pts_db, this->name, this->keyid,
|
||||||
|
algo, &this->count))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
vid = this->name->get_vendor_id(this->name);
|
||||||
|
name = this->name->get_name(this->name);
|
||||||
|
names = pts_components->get_comp_func_names(pts_components, vid);
|
||||||
|
|
||||||
|
if (this->count == 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no %N '%N' functional component evidence measurements "
|
||||||
|
"available", pen_names, vid, names, name);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence measurements",
|
||||||
|
this->count, pen_names, vid, names, name);
|
||||||
|
}
|
||||||
|
|
||||||
if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
|
if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
|
||||||
platform_info, ++this->seq_no, extended_pcr, algo) != SUCCESS)
|
this->keyid, ++this->seq_no, extended_pcr, algo) != SUCCESS)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
@@ -281,7 +314,7 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this->seq_no < IMA_SEQUENCE) ? NEED_MORE : SUCCESS;
|
return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_component_t, destroy, void,
|
METHOD(pts_component_t, destroy, void,
|
||||||
@@ -295,6 +328,7 @@ METHOD(pts_component_t, destroy, void,
|
|||||||
}
|
}
|
||||||
this->list->destroy_function(this->list, (void *)free_entry);
|
this->list->destroy_function(this->list, (void *)free_entry);
|
||||||
this->name->destroy(this->name);
|
this->name->destroy(this->name);
|
||||||
|
free(this->keyid.ptr);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,12 @@
|
|||||||
#include "ita_comp_tboot.h"
|
#include "ita_comp_tboot.h"
|
||||||
#include "ita_comp_func_name.h"
|
#include "ita_comp_func_name.h"
|
||||||
|
|
||||||
|
#include "libpts.h"
|
||||||
#include "pts/components/pts_component.h"
|
#include "pts/components/pts_component.h"
|
||||||
#include "pts/components/pts_comp_evidence.h"
|
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <pen/pen.h>
|
#include <pen/pen.h>
|
||||||
|
|
||||||
#define TBOOT_SEQUENCE 2
|
|
||||||
|
|
||||||
typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
|
typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,11 +46,21 @@ struct pts_ita_comp_tboot_t {
|
|||||||
*/
|
*/
|
||||||
u_int32_t depth;
|
u_int32_t depth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AIK keyid
|
||||||
|
*/
|
||||||
|
chunk_t keyid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time of TBOOT measurement
|
* Time of TBOOT measurement
|
||||||
*/
|
*/
|
||||||
time_t measurement_time;
|
time_t measurement_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected measurement count
|
||||||
|
*/
|
||||||
|
int count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measurement sequence number
|
* Measurement sequence number
|
||||||
*/
|
*/
|
||||||
@@ -144,7 +152,7 @@ METHOD(pts_component_t, measure, status_t,
|
|||||||
this->measurement_time, measurement);
|
this->measurement_time, measurement);
|
||||||
evid->set_pcr_info(evid, pcr_before, pcr_after);
|
evid->set_pcr_info(evid, pcr_before, pcr_after);
|
||||||
|
|
||||||
return (this->seq_no < TBOOT_SEQUENCE) ? NEED_MORE : SUCCESS;
|
return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_component_t, verify, status_t,
|
METHOD(pts_component_t, verify, status_t,
|
||||||
@@ -152,27 +160,50 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
pts_comp_evidence_t *evidence)
|
pts_comp_evidence_t *evidence)
|
||||||
{
|
{
|
||||||
bool has_pcr_info;
|
bool has_pcr_info;
|
||||||
char *platform_info;
|
u_int32_t extended_pcr, vid, name;
|
||||||
u_int32_t extended_pcr;
|
enum_name_t *names;
|
||||||
pts_meas_algorithms_t algo;
|
pts_meas_algorithms_t algo;
|
||||||
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, hash;
|
chunk_t measurement, pcr_before, pcr_after;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
||||||
&algo, &transform, &measurement_time);
|
&algo, &transform, &measurement_time);
|
||||||
|
|
||||||
|
if (!this->keyid.ptr)
|
||||||
|
{
|
||||||
|
if (!pts->get_aik_keyid(pts, &this->keyid))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
this->keyid = chunk_clone(this->keyid);
|
||||||
|
|
||||||
|
if (!pts_db)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "pts database not available");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!pts_db->get_comp_measurement_count(pts_db, this->name, this->keyid,
|
||||||
|
algo, &this->count))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
vid = this->name->get_vendor_id(this->name);
|
||||||
|
name = this->name->get_name(this->name);
|
||||||
|
names = pts_components->get_comp_func_names(pts_components, vid);
|
||||||
|
|
||||||
|
if (this->count == 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no %N '%N' functional component evidence measurements "
|
||||||
|
"available", pen_names, vid, names, name);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence measurements",
|
||||||
|
this->count, pen_names, vid, names, name);
|
||||||
|
}
|
||||||
|
|
||||||
if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
|
if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
|
||||||
platform_info, ++this->seq_no, extended_pcr, algo) != SUCCESS)
|
this->keyid, ++this->seq_no, extended_pcr, algo) != SUCCESS)
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
@@ -186,13 +217,14 @@ METHOD(pts_component_t, verify, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this->seq_no < TBOOT_SEQUENCE) ? NEED_MORE : SUCCESS;
|
return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_component_t, destroy, void,
|
METHOD(pts_component_t, destroy, void,
|
||||||
pts_ita_comp_tboot_t *this)
|
pts_ita_comp_tboot_t *this)
|
||||||
{
|
{
|
||||||
this->name->destroy(this->name);
|
this->name->destroy(this->name);
|
||||||
|
free(this->keyid.ptr);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-1
@@ -459,6 +459,33 @@ METHOD(pts_t, set_aik, void,
|
|||||||
this->aik = aik->get_ref(aik);
|
this->aik = aik->get_ref(aik);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(pts_t, get_aik_keyid, bool,
|
||||||
|
private_pts_t *this, chunk_t *keyid)
|
||||||
|
{
|
||||||
|
public_key_t *public;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
if (!this->aik)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no AIK certificate available");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
public = this->aik->get_public_key(this->aik);
|
||||||
|
if (!public)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no AIK public key available");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
success = public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, keyid);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no SHA-1 AIK public key info ID available");
|
||||||
|
}
|
||||||
|
public->destroy(public);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(pts_t, hash_file, bool,
|
METHOD(pts_t, hash_file, bool,
|
||||||
private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
|
private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
|
||||||
{
|
{
|
||||||
@@ -932,7 +959,6 @@ METHOD(pts_t, quote_tpm, bool,
|
|||||||
}
|
}
|
||||||
if (this->pcr_select[i] & f)
|
if (this->pcr_select[i] & f)
|
||||||
{
|
{
|
||||||
DBG2(DBG_TNC, "PCR %02d selected for TPM Quote", pcr);
|
|
||||||
result = use_quote2 ?
|
result = use_quote2 ?
|
||||||
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
|
Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
|
||||||
TSS_PCRS_DIRECTION_RELEASE) :
|
TSS_PCRS_DIRECTION_RELEASE) :
|
||||||
@@ -1510,6 +1536,7 @@ pts_t *pts_create(bool is_imc)
|
|||||||
.get_pcr_len = _get_pcr_len,
|
.get_pcr_len = _get_pcr_len,
|
||||||
.get_aik = _get_aik,
|
.get_aik = _get_aik,
|
||||||
.set_aik = _set_aik,
|
.set_aik = _set_aik,
|
||||||
|
.get_aik_keyid = _get_aik_keyid,
|
||||||
.is_path_valid = _is_path_valid,
|
.is_path_valid = _is_path_valid,
|
||||||
.hash_file = _hash_file,
|
.hash_file = _hash_file,
|
||||||
.do_measurements = _do_measurements,
|
.do_measurements = _do_measurements,
|
||||||
|
|||||||
@@ -245,6 +245,14 @@ struct pts_t {
|
|||||||
*/
|
*/
|
||||||
void (*set_aik)(pts_t *this, certificate_t *aik);
|
void (*set_aik)(pts_t *this, certificate_t *aik);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SHA-1 Attestation Identity Public Key Info ID
|
||||||
|
*
|
||||||
|
* @param keyid AIK ID
|
||||||
|
* @return TRUE if AIK ID exists
|
||||||
|
*/
|
||||||
|
bool (*get_aik_keyid)(pts_t *this, chunk_t *keyid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether path is valid file/directory on filesystem
|
* Check whether path is valid file/directory on filesystem
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -69,23 +69,6 @@ METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*,
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
|
|
||||||
private_pts_database_t *this, char *product)
|
|
||||||
{
|
|
||||||
enumerator_t *e;
|
|
||||||
|
|
||||||
/* 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, 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.seq_no",
|
|
||||||
DB_TEXT, product, DB_INT, DB_INT, DB_INT, DB_INT);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
|
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
|
||||||
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
|
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
|
||||||
int id, bool is_dir)
|
int id, bool is_dir)
|
||||||
@@ -114,9 +97,25 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
|
||||||
|
private_pts_database_t *this, chunk_t keyid)
|
||||||
|
{
|
||||||
|
enumerator_t *e;
|
||||||
|
|
||||||
|
/* 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, kc.depth "
|
||||||
|
"FROM components AS c "
|
||||||
|
"JOIN key_component AS kc ON c.id = kc.component "
|
||||||
|
"JOIN keys AS k ON k.id = kc.key "
|
||||||
|
"WHERE k.keyid = ? ORDER BY kc.seq_no",
|
||||||
|
DB_BLOB, keyid, DB_INT, DB_INT, DB_INT, DB_INT);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(pts_database_t, check_comp_measurement, status_t,
|
METHOD(pts_database_t, check_comp_measurement, status_t,
|
||||||
private_pts_database_t *this, chunk_t measurement,
|
private_pts_database_t *this, chunk_t measurement,
|
||||||
pts_comp_func_name_t *comp_name, char *product,
|
pts_comp_func_name_t *comp_name, chunk_t keyid,
|
||||||
int seq_no, int pcr, pts_meas_algorithms_t algo)
|
int seq_no, int pcr, pts_meas_algorithms_t algo)
|
||||||
{
|
{
|
||||||
enumerator_t *e;
|
enumerator_t *e;
|
||||||
@@ -125,14 +124,14 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
|
|||||||
|
|
||||||
e = this->db->query(this->db,
|
e = this->db->query(this->db,
|
||||||
"SELECT ch.hash FROM component_hashes AS ch "
|
"SELECT ch.hash FROM component_hashes AS ch "
|
||||||
"JOIN products AS p ON ch.product = p.id "
|
"JOIN keys AS k ON ch.key = k.id "
|
||||||
"JOIN components AS c ON ch.component = c.id "
|
"JOIN components AS c ON ch.component = c.id "
|
||||||
"WHERE c.vendor_id = ? AND c.name = ? AND c.qualifier = ? "
|
"WHERE c.vendor_id = ? AND c.name = ? AND c.qualifier = ? "
|
||||||
"AND p.name = ? AND ch.seq_no = ? AND ch.pcr = ? AND ch.algo = ? ",
|
"AND k.keyid = ? AND ch.seq_no = ? AND ch.pcr = ? AND ch.algo = ? ",
|
||||||
DB_INT, comp_name->get_vendor_id(comp_name),
|
DB_INT, comp_name->get_vendor_id(comp_name),
|
||||||
DB_INT, comp_name->get_name(comp_name),
|
DB_INT, comp_name->get_name(comp_name),
|
||||||
DB_INT, comp_name->get_qualifier(comp_name),
|
DB_INT, comp_name->get_qualifier(comp_name),
|
||||||
DB_TEXT, product, DB_INT, seq_no, DB_INT, pcr, DB_INT, algo,
|
DB_BLOB, keyid, DB_INT, seq_no, DB_INT, pcr, DB_INT, algo,
|
||||||
DB_BLOB);
|
DB_BLOB);
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
@@ -144,8 +143,6 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
|
|||||||
{
|
{
|
||||||
if (chunk_equals(hash, measurement))
|
if (chunk_equals(hash, measurement))
|
||||||
{
|
{
|
||||||
DBG2(DBG_PTS, "PCR %2d matching component measurement #%d "
|
|
||||||
"found in database", pcr, seq_no);
|
|
||||||
status = SUCCESS;
|
status = SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -170,6 +167,58 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(pts_database_t, get_comp_measurement_count, bool,
|
||||||
|
private_pts_database_t *this, pts_comp_func_name_t *comp_name,
|
||||||
|
chunk_t keyid, pts_meas_algorithms_t algo, int *count)
|
||||||
|
{
|
||||||
|
enumerator_t *e;
|
||||||
|
int kid;
|
||||||
|
bool success = TRUE;
|
||||||
|
|
||||||
|
/* Initialize count */
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
/* Is the AIK registered? */
|
||||||
|
e = this->db->query(this->db,
|
||||||
|
"SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT);
|
||||||
|
if (!e)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no database query enumerator returned");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!e->enumerate(e, &kid))
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid);
|
||||||
|
e->destroy(e);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
e->destroy(e);
|
||||||
|
|
||||||
|
/* Get the number of stored measurements for a given AIK and component */
|
||||||
|
e = this->db->query(this->db,
|
||||||
|
"SELECT COUNT(*) FROM component_hashes AS ch "
|
||||||
|
"JOIN components AS c ON ch.component = c.id "
|
||||||
|
"WHERE c.vendor_id = ? AND c.name = ? AND c.qualifier = ? "
|
||||||
|
"AND ch.key = ? AND ch.algo = ? ",
|
||||||
|
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, kid, DB_INT, algo, DB_INT);
|
||||||
|
if (!e)
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no database query enumerator returned");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!e->enumerate(e, count))
|
||||||
|
{
|
||||||
|
DBG1(DBG_PTS, "no component measurement count returned from database");
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
e->destroy(e);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(pts_database_t, destroy, void,
|
METHOD(pts_database_t, destroy, void,
|
||||||
private_pts_database_t *this)
|
private_pts_database_t *this)
|
||||||
{
|
{
|
||||||
@@ -191,6 +240,7 @@ pts_database_t *pts_database_create(char *uri)
|
|||||||
.create_comp_evid_enumerator = _create_comp_evid_enumerator,
|
.create_comp_evid_enumerator = _create_comp_evid_enumerator,
|
||||||
.create_file_hash_enumerator = _create_file_hash_enumerator,
|
.create_file_hash_enumerator = _create_file_hash_enumerator,
|
||||||
.check_comp_measurement = _check_comp_measurement,
|
.check_comp_measurement = _check_comp_measurement,
|
||||||
|
.get_comp_measurement_count = _get_comp_measurement_count,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.db = lib->db->create(lib->db, uri),
|
.db = lib->db->create(lib->db, uri),
|
||||||
|
|||||||
@@ -51,15 +51,6 @@ struct pts_database_t {
|
|||||||
enumerator_t* (*create_file_meta_enumerator)(pts_database_t *this,
|
enumerator_t* (*create_file_meta_enumerator)(pts_database_t *this,
|
||||||
char *product);
|
char *product);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get functional components to request evidence of
|
|
||||||
*
|
|
||||||
* @param product Software product (os, vpn client, etc.)
|
|
||||||
* @return Enumerator over all matching components
|
|
||||||
*/
|
|
||||||
enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this,
|
|
||||||
char *product);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get stored measurement hash for single file or directory entries
|
* Get stored measurement hash for single file or directory entries
|
||||||
*
|
*
|
||||||
@@ -73,21 +64,42 @@ struct pts_database_t {
|
|||||||
char *product, pts_meas_algorithms_t algo,
|
char *product, pts_meas_algorithms_t algo,
|
||||||
int id, bool is_dir);
|
int id, bool is_dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get functional components to request evidence of
|
||||||
|
*
|
||||||
|
* @param keyid SHA-1 hash of AIK public key info
|
||||||
|
* @return Enumerator over all matching components
|
||||||
|
*/
|
||||||
|
enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this,
|
||||||
|
chunk_t keyid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check a functional component measurement against value stored in database
|
* Check a functional component measurement against value stored in database
|
||||||
*
|
*
|
||||||
* @param measurement measurement hash
|
* @param measurement measurement hash
|
||||||
* @param comp_name Component Functional Name
|
* @param comp_name Component Functional Name
|
||||||
* @param product Software product (os, vpn client, etc.)
|
* @param keyid SHA-1 hash of AIK public key info
|
||||||
* @param seq_no Measurement sequence number
|
* @param seq_no Measurement sequence number
|
||||||
* @param prc Number of the PCR the measurement was extended into
|
* @param prc Number of the PCR the measurement was extended into
|
||||||
* @param algo Hash algorithm used for measurement
|
* @param algo Hash algorithm used for measurement
|
||||||
* @return return code
|
* @return return code
|
||||||
*/
|
*/
|
||||||
status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
|
status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
|
||||||
pts_comp_func_name_t *comp_name, char *product,
|
pts_comp_func_name_t *comp_name, chunk_t keyid,
|
||||||
int seq_no, int pcr, pts_meas_algorithms_t algo);
|
int seq_no, int pcr, pts_meas_algorithms_t algo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of measurements for a functional component and AIK
|
||||||
|
*
|
||||||
|
* @param comp_name Component Functional Name
|
||||||
|
* @param keyid SHA-1 hash of AIK public key info
|
||||||
|
* @param algo Hash algorithm used for measurement
|
||||||
|
* @return measurement count
|
||||||
|
*/
|
||||||
|
bool (*get_comp_measurement_count)(pts_database_t *this,
|
||||||
|
pts_comp_func_name_t *comp_name, chunk_t keyid,
|
||||||
|
pts_meas_algorithms_t algo, int *count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys a pts_database_t object.
|
* Destroys a pts_database_t object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user