diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libpts/plugins/imv_attestation/attest.c | 38 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/attest_db.c | 672 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/attest_db.h | 69 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/attest_usage.c | 32 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/data.sql | 608 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/imv_attestation_build.c | 17 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/imv_attestation_process.c | 12 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/tables.sql | 55 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_ima.c | 62 | ||||
-rw-r--r-- | src/libpts/pts/components/ita/ita_comp_tboot.c | 68 | ||||
-rw-r--r-- | src/libpts/pts/pts.c | 29 | ||||
-rw-r--r-- | src/libpts/pts/pts.h | 8 | ||||
-rw-r--r-- | src/libpts/pts/pts_database.c | 96 | ||||
-rw-r--r-- | src/libpts/pts/pts_database.h | 34 |
14 files changed, 1162 insertions, 638 deletions
diff --git a/src/libpts/plugins/imv_attestation/attest.c b/src/libpts/plugins/imv_attestation/attest.c index ca9efab10..ac91b5aa7 100644 --- a/src/libpts/plugins/imv_attestation/attest.c +++ b/src/libpts/plugins/imv_attestation/attest.c @@ -97,10 +97,12 @@ static void do_args(int argc, char *argv[]) enum { OP_UNDEF, OP_USAGE, - OP_FILES, + OP_KEYS, OP_COMPONENTS, - OP_PRODUCTS, + OP_FILES, OP_HASHES, + OP_MEASUREMENTS, + OP_PRODUCTS, OP_ADD, OP_DEL, } op = OP_UNDEF; @@ -116,8 +118,10 @@ static void do_args(int argc, char *argv[]) { "help", no_argument, NULL, 'h' }, { "components", no_argument, NULL, 'c' }, { "files", no_argument, NULL, 'f' }, + { "keys", no_argument, NULL, 'k' }, { "products", no_argument, NULL, 'p' }, { "hashes", no_argument, NULL, 'H' }, + { "measurements", no_argument, NULL, 'M' }, { "add", no_argument, NULL, 'a' }, { "delete", 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' }, { "dir", required_argument, NULL, 'D' }, { "file", required_argument, NULL, 'F' }, + { "key", required_argument, NULL, 'K' }, + { "owner", required_argument, NULL, 'O' }, { "product", required_argument, NULL, 'P' }, { "sha1", no_argument, NULL, '1' }, { "sha256", no_argument, NULL, '2' }, @@ -137,6 +143,7 @@ static void do_args(int argc, char *argv[]) { "fid", required_argument, NULL, '5' }, { "pid", required_argument, NULL, '6' }, { "cid", required_argument, NULL, '7' }, + { "kid", required_argument, NULL, '8' }, { 0,0,0,0 } }; @@ -154,12 +161,18 @@ static void do_args(int argc, char *argv[]) case 'f': op = OP_FILES; continue; + case 'k': + op = OP_KEYS; + continue; case 'p': op = OP_PRODUCTS; continue; case 'H': op = OP_HASHES; continue; + case 'M': + op = OP_MEASUREMENTS; + continue; case 'a': op = OP_ADD; continue; @@ -199,6 +212,15 @@ static void do_args(int argc, char *argv[]) exit(EXIT_FAILURE); } 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': if (!attest->set_product(attest, optarg, op == OP_ADD)) { @@ -238,6 +260,12 @@ static void do_args(int argc, char *argv[]) exit(EXIT_FAILURE); } continue; + case '8': + if (!attest->set_kid(attest, atoi(optarg))) + { + exit(EXIT_FAILURE); + } + continue; } break; } @@ -250,6 +278,9 @@ static void do_args(int argc, char *argv[]) case OP_PRODUCTS: attest->list_products(attest); break; + case OP_KEYS: + attest->list_keys(attest); + break; case OP_COMPONENTS: attest->list_components(attest); break; @@ -259,6 +290,9 @@ static void do_args(int argc, char *argv[]) case OP_HASHES: attest->list_hashes(attest); break; + case OP_MEASUREMENTS: + attest->list_measurements(attest); + break; case OP_ADD: attest->add(attest); break; diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c index a9f1f710d..10c719bff 100644 --- a/src/libpts/plugins/imv_attestation/attest_db.c +++ b/src/libpts/plugins/imv_attestation/attest_db.c @@ -31,19 +31,34 @@ struct private_attest_db_t { attest_db_t public; /** - * Software product to be queried + * Component Functional Name to be queried */ - char *product; + pts_comp_func_name_t *cfn; /** - * Primary key of software product to be queried + * Primary key of the Component Functional Name to be queried */ - int pid; + int cid; /** - * TRUE if product has been set + * TRUE if Component Functional Name has been set */ - bool product_set; + bool comp_set; + + /** + * Directory containing the Measurement file to be queried + */ + char *dir; + + /** + * Primary key of the directory to be queried + */ + int did; + + /** + * TRUE if directory has been set + */ + bool dir_set; /** * Measurement file to be queried @@ -61,34 +76,34 @@ struct private_attest_db_t { bool file_set; /** - * Directory containing the Measurement file to be queried + * AIK to be queried */ - char *dir; + chunk_t key; /** - * Primary key of the directory to be queried + * Primary key of the AIK to be queried */ - int did; + int kid; /** - * TRUE if directory has been set + * TRUE if AIK has been set */ - bool dir_set; + bool key_set; /** - * Component Functional Name to be queried + * Software product to be queried */ - pts_comp_func_name_t *cfn; + char *product; /** - * Primary key of the Component Functional Name to be queried + * Primary key of software product to be queried */ - int cid; + int pid; /** - * TRUE if Component Functional Name has been set + * TRUE if product has been set */ - bool comp_set; + bool product_set; /** * File measurement hash algorithm @@ -96,6 +111,11 @@ struct private_attest_db_t { pts_meas_algorithms_t algo; /** + * Optional owner (user/host name) + */ + char *owner; + + /** * Attestation database */ database_t *db; @@ -125,79 +145,185 @@ char* print_cfn(pts_comp_func_name_t *cfn) return buf; } -METHOD(attest_db_t, set_product, bool, - private_attest_db_t *this, char *product, bool create) +METHOD(attest_db_t, set_component, bool, + private_attest_db_t *this, char *comp, bool create) { enumerator_t *e; + char *pos1, *pos2; + int vid, name, qualifier; + pts_comp_func_name_t *cfn; - if (this->product_set) + if (this->comp_set) { - printf("product has already been set\n"); + printf("component has already been set\n"); return FALSE; } - this->product = strdup(product); - e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?", - DB_TEXT, product, DB_INT); + /* parse component string */ + pos1 = strchr(comp, '/'); + pos2 = strchr(comp, '-'); + if (!pos1 || !pos2) + { + printf("component string must have the form \"vendor_id/name-qualifier\"\n"); + return FALSE; + } + vid = atoi(comp); + name = atoi(pos1 + 1); + qualifier = atoi(pos2 + 1); + cfn = pts_comp_func_name_create(vid, name, qualifier); + + e = this->db->query(this->db, + "SELECT id FROM components " + "WHERE vendor_id = ? AND name = ? AND qualifier = ?", + DB_INT, vid, DB_INT, name, DB_INT, qualifier, DB_INT); if (e) { - if (e->enumerate(e, &this->pid)) + if (e->enumerate(e, &this->cid)) { - this->product_set = TRUE; + this->comp_set = TRUE; + this->cfn = cfn; } e->destroy(e); } - if (this->product_set) + if (this->comp_set) { return TRUE; } if (!create) { - printf("product '%s' not found in database\n", product); + printf("component '%s' not found in database\n", print_cfn(cfn)); + cfn->destroy(cfn); return FALSE; } /* Add a new database entry */ - this->product_set = this->db->execute(this->db, &this->pid, - "INSERT INTO products (name) VALUES (?)", - DB_TEXT, product) == 1; + this->comp_set = this->db->execute(this->db, &this->cid, + "INSERT INTO components (vendor_id, name, qualifier) " + "VALUES (?, ?, ?)", + DB_INT, vid, DB_INT, name, DB_INT, qualifier) == 1; - printf("product '%s' %sinserted into database\n", product, - this->product_set ? "" : "could not be "); + printf("component '%s' %sinserted into database\n", print_cfn(cfn), + this->comp_set ? "" : "could not be "); + if (this->comp_set) + { + this->cfn = cfn; + } + else + { + cfn->destroy(cfn); + } + return this->comp_set; +} - return this->product_set; +METHOD(attest_db_t, set_cid, bool, + private_attest_db_t *this, int cid) +{ + enumerator_t *e; + int vid, name, qualifier; + + if (this->comp_set) + { + printf("component has already been set\n"); + return FALSE; + } + this->cid = cid; + + e = this->db->query(this->db, "SELECT vendor_id, name, qualifier " + "FROM components WHERE id = ?", + DB_INT, cid, DB_INT, DB_INT, DB_INT); + if (e) + { + if (e->enumerate(e, &vid, &name, &qualifier)) + { + this->cfn = pts_comp_func_name_create(vid, name, qualifier); + this->comp_set = TRUE; + } + else + { + printf("no component found with cid %d\n", cid); + } + e->destroy(e); + } + return this->comp_set; } -METHOD(attest_db_t, set_pid, bool, - private_attest_db_t *this, int pid) +METHOD(attest_db_t, set_directory, bool, + private_attest_db_t *this, char *dir, bool create) { enumerator_t *e; - char *product; - if (this->product_set) + if (this->dir_set) { - printf("product has already been set\n"); + printf("directory has already been set\n"); return FALSE; } - this->pid = pid; + free(this->dir); + this->dir = strdup(dir); - e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?", - DB_INT, pid, DB_TEXT); + e = this->db->query(this->db, + "SELECT id FROM files WHERE type = 1 AND path = ?", + DB_TEXT, dir, DB_INT); if (e) { - if (e->enumerate(e, &product)) + if (e->enumerate(e, &this->did)) { - this->product = strdup(product); - this->product_set = TRUE; + this->dir_set = TRUE; + } + e->destroy(e); + } + if (this->dir_set) + { + return TRUE; + } + + if (!create) + { + printf("directory '%s' not found in database\n", dir); + return FALSE; + } + + /* Add a new database entry */ + this->dir_set = this->db->execute(this->db, &this->did, + "INSERT INTO files (type, path) VALUES (1, ?)", + DB_TEXT, dir) == 1; + + printf("directory '%s' %sinserted into database\n", dir, + this->dir_set ? "" : "could not be "); + + return this->dir_set; +} + +METHOD(attest_db_t, set_did, bool, + private_attest_db_t *this, int did) +{ + enumerator_t *e; + char *dir; + + if (this->dir_set) + { + printf("directory has already been set\n"); + return FALSE; + } + this->did = did; + + e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?", + DB_INT, did, DB_TEXT); + if (e) + { + if (e->enumerate(e, &dir)) + { + free(this->dir); + this->dir = strdup(dir); + this->dir_set = TRUE; } else { - printf("no product found with pid %d in database\n", pid); + printf("no directory found with did %d\n", did); } e->destroy(e); } - return this->product_set; + return this->dir_set; } METHOD(attest_db_t, set_file, bool, @@ -275,185 +401,164 @@ METHOD(attest_db_t, set_fid, bool, return this->file_set; } -METHOD(attest_db_t, set_directory, bool, - private_attest_db_t *this, char *dir, bool create) +METHOD(attest_db_t, set_key, bool, + private_attest_db_t *this, char *key, bool create) { enumerator_t *e; + char *owner; - if (this->dir_set) + if (this->key_set) { - printf("directory has already been set\n"); + printf("key has already been set\n"); return FALSE; } - free(this->dir); - this->dir = strdup(dir); + this->key = chunk_from_hex(chunk_create(key, strlen(key)), NULL); - e = this->db->query(this->db, - "SELECT id FROM files WHERE type = 1 AND path = ?", - DB_TEXT, dir, DB_INT); + e = this->db->query(this->db, "SELECT id, owner FROM keys WHERE keyid= ?", + DB_BLOB, this->key, DB_INT, DB_TEXT); if (e) { - if (e->enumerate(e, &this->did)) + if (e->enumerate(e, &this->kid, &owner)) { - this->dir_set = TRUE; + this->owner = strdup(owner); + this->key_set = TRUE; } e->destroy(e); } - if (this->dir_set) + if (this->key_set) { return TRUE; } if (!create) { - printf("directory '%s' not found in database\n", dir); + printf("key '%#B' not found in database\n", &this->key); return FALSE; } /* Add a new database entry */ - this->dir_set = this->db->execute(this->db, &this->did, - "INSERT INTO files (type, path) VALUES (1, ?)", - DB_TEXT, dir) == 1; + if (!this->owner) + { + this->owner = strdup(""); + } + this->key_set = this->db->execute(this->db, &this->kid, + "INSERT INTO keys (keyid, owner) VALUES (?, ?)", + DB_BLOB, this->key, DB_TEXT, this->owner) == 1; - printf("directory '%s' %sinserted into database\n", dir, - this->dir_set ? "" : "could not be "); + printf("key '%#B' %sinserted into database\n", &this->key, + this->key_set ? "" : "could not be "); - return this->dir_set; -} + return this->key_set; -METHOD(attest_db_t, set_did, bool, - private_attest_db_t *this, int did) +}; + +METHOD(attest_db_t, set_kid, bool, + private_attest_db_t *this, int kid) { enumerator_t *e; - char *dir; + chunk_t key; + char *owner; - if (this->dir_set) + if (this->key_set) { - printf("directory has already been set\n"); + printf("key has already been set\n"); return FALSE; } - this->did = did; + this->kid = kid; - e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?", - DB_INT, did, DB_TEXT); + e = this->db->query(this->db, "SELECT keyid, owner FROM keys WHERE id = ?", + DB_INT, kid, DB_BLOB, DB_TEXT); if (e) { - if (e->enumerate(e, &dir)) + if (e->enumerate(e, &key, &owner)) { - free(this->dir); - this->dir = strdup(dir); - this->dir_set = TRUE; + this->owner = strdup(owner); + this->key = chunk_clone(key); + this->key_set = TRUE; } else { - printf("no directory found with did %d\n", did); + printf("no key found with kid %d\n", kid); } e->destroy(e); } - return this->dir_set; -} + return this->key_set; -METHOD(attest_db_t, set_component, bool, - private_attest_db_t *this, char *comp, bool create) +}; + +METHOD(attest_db_t, set_product, bool, + private_attest_db_t *this, char *product, bool create) { enumerator_t *e; - char *pos1, *pos2; - int vid, name, qualifier; - pts_comp_func_name_t *cfn; - if (this->comp_set) - { - printf("component has already been set\n"); - return FALSE; - } - - /* parse component string */ - pos1 = strchr(comp, '/'); - pos2 = strchr(comp, '-'); - if (!pos1 || !pos2) + if (this->product_set) { - printf("component string must have the form \"vendor_id/name-qualifier\"\n"); + printf("product has already been set\n"); return FALSE; } - vid = atoi(comp); - name = atoi(pos1 + 1); - qualifier = atoi(pos2 + 1); - cfn = pts_comp_func_name_create(vid, name, qualifier); + this->product = strdup(product); - e = this->db->query(this->db, - "SELECT id FROM components " - "WHERE vendor_id = ? AND name = ? AND qualifier = ?", - DB_INT, vid, DB_INT, name, DB_INT, qualifier, DB_INT); + e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?", + DB_TEXT, product, DB_INT); if (e) { - if (e->enumerate(e, &this->cid)) + if (e->enumerate(e, &this->pid)) { - this->comp_set = TRUE; - this->cfn = cfn; + this->product_set = TRUE; } e->destroy(e); } - if (this->comp_set) + if (this->product_set) { return TRUE; } if (!create) { - printf("component '%s' not found in database\n", print_cfn(cfn)); - cfn->destroy(cfn); + printf("product '%s' not found in database\n", product); return FALSE; } /* Add a new database entry */ - this->comp_set = this->db->execute(this->db, &this->cid, - "INSERT INTO components (vendor_id, name, qualifier) " - "VALUES (?, ?, ?)", - DB_INT, vid, DB_INT, name, DB_INT, qualifier) == 1; + this->product_set = this->db->execute(this->db, &this->pid, + "INSERT INTO products (name) VALUES (?)", + DB_TEXT, product) == 1; - printf("component '%s' %sinserted into database\n", print_cfn(cfn), - this->comp_set ? "" : "could not be "); - if (this->comp_set) - { - this->cfn = cfn; - } - else - { - cfn->destroy(cfn); - } - return this->comp_set; + printf("product '%s' %sinserted into database\n", product, + this->product_set ? "" : "could not be "); + + return this->product_set; } -METHOD(attest_db_t, set_cid, bool, - private_attest_db_t *this, int cid) +METHOD(attest_db_t, set_pid, bool, + private_attest_db_t *this, int pid) { enumerator_t *e; - int vid, name, qualifier; + char *product; - if (this->comp_set) + if (this->product_set) { - printf("component has already been set\n"); + printf("product has already been set\n"); return FALSE; } - this->cid = cid; + this->pid = pid; - e = this->db->query(this->db, "SELECT vendor_id, name, qualifier " - "FROM components WHERE id = ?", - DB_INT, cid, DB_INT, DB_INT, DB_INT); + e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?", + DB_INT, pid, DB_TEXT); if (e) { - if (e->enumerate(e, &vid, &name, &qualifier)) + if (e->enumerate(e, &product)) { - this->cfn = pts_comp_func_name_create(vid, name, qualifier); - this->comp_set = TRUE; + this->product = strdup(product); + this->product_set = TRUE; } else { - printf("no component found with cid %d\n", cid); + printf("no product found with pid %d in database\n", pid); } e->destroy(e); } - return this->comp_set; + return this->product_set; } METHOD(attest_db_t, set_algo, void, @@ -462,6 +567,13 @@ METHOD(attest_db_t, set_algo, void, this->algo = algo; } +METHOD(attest_db_t, set_owner, void, + private_attest_db_t *this, char *owner) +{ + free(this->owner); + this->owner = strdup(owner); +} + METHOD(attest_db_t, list_components, void, private_attest_db_t *this) { @@ -469,14 +581,14 @@ METHOD(attest_db_t, list_components, void, pts_comp_func_name_t *cfn; int cid, vid, name, qualifier, count = 0; - if (this->pid) + if (this->kid) { e = this->db->query(this->db, "SELECT c.id, c.vendor_id, c.name, c.qualifier " "FROM components AS c " - "JOIN product_component AS pc ON c.id = pc.component " - "WHERE pc.product = ? ORDER BY c.vendor_id, c.name, c.qualifier", - DB_INT, this->pid, DB_INT, DB_INT, DB_INT, DB_INT); + "JOIN key_component AS kc ON c.id = kc.component " + "WHERE kc.key = ? ORDER BY c.vendor_id, c.name, c.qualifier", + DB_INT, this->kid, DB_INT, DB_INT, DB_INT, DB_INT); } else { @@ -497,14 +609,63 @@ METHOD(attest_db_t, list_components, void, e->destroy(e); printf("%d component%s found", count, (count == 1) ? "" : "s"); - if (this->product_set) + if (this->key_set) { - printf(" for product '%s'", this->product); + printf(" for key %#B", &this->key); } printf("\n"); } } +METHOD(attest_db_t, list_keys, void, + private_attest_db_t *this) +{ + enumerator_t *e; + chunk_t keyid; + char *owner; + int kid, count = 0; + + if (this->cid) + { + e = this->db->query(this->db, + "SELECT k.id, k.keyid, k.owner FROM keys AS k " + "JOIN key_component AS kc ON k.id = kc.key " + "WHERE kc.component = ? ORDER BY k.keyid", + DB_INT, this->cid, DB_INT, DB_BLOB, DB_TEXT); + if (e) + { + while (e->enumerate(e, &kid, &keyid, &owner)) + { + printf("%3d: %#B '%s'\n", kid, &keyid, owner); + count++; + } + e->destroy(e); + } + } + else + { + e = this->db->query(this->db, "SELECT id, keyid, owner FROM keys " + "ORDER BY keyid", + DB_INT, DB_BLOB, DB_TEXT); + if (e) + { + while (e->enumerate(e, &kid, &keyid, &owner)) + { + printf("%3d: %#B '%s'\n", kid, &keyid, owner); + count++; + } + e->destroy(e); + } + } + + printf("%d key%s found", count, (count == 1) ? "" : "s"); + if (this->comp_set) + { + printf(" for component '%s'", print_cfn(this->cfn)); + } + printf("\n"); +} + METHOD(attest_db_t, list_files, void, private_attest_db_t *this) { @@ -584,23 +745,6 @@ METHOD(attest_db_t, list_products, void, e->destroy(e); } } - else if (this->cid) - { - e = this->db->query(this->db, - "SELECT p.id, p.name FROM products AS p " - "JOIN product_component AS pc ON p.id = pc.product " - "WHERE pc.component = ? ORDER BY p.name", - DB_INT, this->cid, DB_INT, DB_TEXT); - if (e) - { - while (e->enumerate(e, &pid, &product, &meas, &meta)) - { - printf("%3d: %s\n", pid, product); - count++; - } - e->destroy(e); - } - } else { e = this->db->query(this->db, "SELECT id, name FROM products " @@ -622,10 +766,6 @@ METHOD(attest_db_t, list_products, void, { printf(" for file '%s'", this->file); } - else if (this->comp_set) - { - printf(" for component '%s'", print_cfn(this->cfn)); - } printf("\n"); } @@ -672,34 +812,7 @@ METHOD(attest_db_t, list_hashes, void, dir = strdup(""); - if (this->pid && this->fid && this->cid) - { - e = this->db->query(this->db, - "SELECT hash FROM file_hashes " - "WHERE algo = ? AND file = ? AND component = ? AND product = ?", - DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->cid, - DB_INT, this->pid, DB_BLOB); - if (e) - { - while (e->enumerate(e, &hash)) - { - if (this->fid != fid_old) - { - printf("%3d: %s%s%s\n", this->fid, this->dir, - slash(this->dir, this->file) ? "/" : "", this->file); - fid_old = this->fid; - } - printf(" %#B '%s'\n", &hash, this->product); - count++; - } - e->destroy(e); - - printf("%d %N value%s found for component '%s'\n", count, - hash_algorithm_names, pts_meas_algo_to_hash(this->algo), - (count == 1) ? "" : "s", print_cfn(this->cfn)); - } - } - else if (this->pid && this->fid) + if (this->pid && this->fid) { e = this->db->query(this->db, "SELECT hash FROM file_hashes " @@ -824,6 +937,110 @@ METHOD(attest_db_t, list_hashes, void, free(dir); } +METHOD(attest_db_t, list_measurements, void, + private_attest_db_t *this) +{ + enumerator_t *e; + chunk_t hash, keyid; + pts_comp_func_name_t *cfn; + char *owner; + int seq_no, pcr, vid, name, qualifier; + int cid, cid_old = 0, kid, kid_old = 0, count = 0; + + if (this->kid && this->cid) + { + e = this->db->query(this->db, + "SELECT ch.seq_no, ch.pcr, ch.hash, k.owner " + "FROM component_hashes AS ch " + "JOIN keys AS k ON k.id = ch.key " + "WHERE ch.algo = ? AND ch.key = ? AND ch.component = ? " + "ORDER BY seq_no", + DB_INT, this->algo, DB_INT, this->kid, DB_INT, this->cid, + DB_INT, DB_INT, DB_BLOB, DB_TEXT); + if (e) + { + while (e->enumerate(e, &seq_no, &pcr, &hash, &owner)) + { + if (this->kid != kid_old) + { + printf("%3d: %#B '%s'\n", this->kid, &this->key, owner); + kid_old = this->kid; + } + printf("%5d %02d %#B\n", seq_no, pcr, &hash); + count++; + } + e->destroy(e); + + printf("%d %N value%s found for component '%s'\n", count, + hash_algorithm_names, pts_meas_algo_to_hash(this->algo), + (count == 1) ? "" : "s", print_cfn(this->cfn)); + } + } + else if (this->cid) + { + e = this->db->query(this->db, + "SELECT ch.seq_no, ch.pcr, ch.hash, k.id, k.keyid, k.owner " + "FROM component_hashes AS ch " + "JOIN keys AS k ON k.id = ch.key " + "WHERE ch.algo = ? AND ch.component = ? " + "ORDER BY keyid, seq_no", + DB_INT, this->algo, DB_INT, this->cid, + DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, DB_TEXT); + if (e) + { + while (e->enumerate(e, &seq_no, &pcr, &hash, &kid, &keyid, &owner)) + { + if (kid != kid_old) + { + printf("%3d: %#B '%s'\n", kid, &keyid, owner); + kid_old = kid; + } + printf("%5d %02d %#B\n", seq_no, pcr, &hash); + count++; + } + e->destroy(e); + + printf("%d %N value%s found for component '%s'\n", count, + hash_algorithm_names, pts_meas_algo_to_hash(this->algo), + (count == 1) ? "" : "s", print_cfn(this->cfn)); + } + + } + else if (this->kid) + { + e = this->db->query(this->db, + "SELECT ch.seq_no, ch.pcr, ch.hash, " + "c.id, c.vendor_id, c.name, c.qualifier " + "FROM component_hashes AS ch " + "JOIN components AS c ON c.id = ch.component " + "WHERE ch.algo = ? AND ch.key = ? " + "ORDER BY vendor_id, name, qualifier, seq_no", + DB_INT, this->algo, DB_INT, this->kid, DB_INT, DB_INT, DB_BLOB, + DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT); + if (e) + { + while (e->enumerate(e, &seq_no, &pcr, &hash, &cid, &vid, &name, + &qualifier)) + { + if (cid != cid_old) + { + cfn = pts_comp_func_name_create(vid, name, qualifier); + printf("%3d: %s\n", cid, print_cfn(cfn)); + cfn->destroy(cfn); + cid_old = cid; + } + printf("%5d %02d %#B\n", seq_no, pcr, &hash); + count++; + } + e->destroy(e); + + printf("%d %N value%s found for key %#B '%s'\n", count, + hash_algorithm_names, pts_meas_algo_to_hash(this->algo), + (count == 1) ? "" : "s", &this->key, this->owner); + } + } +} + METHOD(attest_db_t, add, bool, private_attest_db_t *this) { @@ -841,13 +1058,30 @@ METHOD(attest_db_t, delete, bool, return FALSE; } - if (this->pid) + if (this->kid && this->did) + { + printf("deletion of key/component entries not supported yet\n"); + return FALSE; + } + + if (this->cid) { success = this->db->execute(this->db, NULL, - "DELETE FROM products WHERE id = ?", - DB_UINT, this->pid) > 0; + "DELETE FROM components WHERE id = ?", + DB_UINT, this->cid) > 0; - printf("product '%s' %sdeleted from database\n", this->product, + printf("component '%s' %sdeleted from database\n", print_cfn(this->cfn), + success ? "" : "could not be "); + return success; + } + + if (this->did) + { + success = this->db->execute(this->db, NULL, + "DELETE FROM files WHERE type = 1 AND id = ?", + DB_UINT, this->did) > 0; + + printf("directory '%s' %sdeleted from database\n", this->dir, success ? "" : "could not be "); return success; } @@ -863,24 +1097,23 @@ METHOD(attest_db_t, delete, bool, return success; } - if (this->did) + if (this->kid) { success = this->db->execute(this->db, NULL, - "DELETE FROM files WHERE type = 1 AND id = ?", - DB_UINT, this->did) > 0; + "DELETE FROM keys WHERE id = ?", + DB_UINT, this->kid) > 0; - printf("directory '%s' %sdeleted from database\n", this->dir, + printf("key %#B %sdeleted from database\n", &this->key, success ? "" : "could not be "); return success; } - - if (this->cid) + if (this->pid) { success = this->db->execute(this->db, NULL, - "DELETE FROM components WHERE id = ?", - DB_UINT, this->cid) > 0; + "DELETE FROM products WHERE id = ?", + DB_UINT, this->pid) > 0; - printf("component '%s' %sdeleted from database\n", print_cfn(this->cfn), + printf("product '%s' %sdeleted from database\n", this->product, success ? "" : "could not be "); return success; } @@ -897,6 +1130,8 @@ METHOD(attest_db_t, destroy, void, free(this->product); free(this->file); free(this->dir); + free(this->owner); + free(this->key.ptr); free(this); } @@ -909,19 +1144,24 @@ attest_db_t *attest_db_create(char *uri) INIT(this, .public = { - .set_product = _set_product, - .set_pid = _set_pid, - .set_file = _set_file, - .set_fid = _set_fid, - .set_directory = _set_directory, - .set_did = _set_did, .set_component = _set_component, .set_cid = _set_cid, + .set_directory = _set_directory, + .set_did = _set_did, + .set_file = _set_file, + .set_fid = _set_fid, + .set_key = _set_key, + .set_kid = _set_kid, + .set_product = _set_product, + .set_pid = _set_pid, .set_algo = _set_algo, + .set_owner = _set_owner, .list_products = _list_products, .list_files = _list_files, .list_components = _list_components, + .list_keys = _list_keys, .list_hashes = _list_hashes, + .list_measurements = _list_measurements, .add = _add, .delete = _delete, .destroy = _destroy, diff --git a/src/libpts/plugins/imv_attestation/attest_db.h b/src/libpts/plugins/imv_attestation/attest_db.h index 6669a76a7..80a8f4cd4 100644 --- a/src/libpts/plugins/imv_attestation/attest_db.h +++ b/src/libpts/plugins/imv_attestation/attest_db.h @@ -34,21 +34,38 @@ typedef struct attest_db_t attest_db_t; struct attest_db_t { /** - * Set software product to be queried + * Set functional component to be queried * - * @param product software product + * @param comp functional component * @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); + bool (*set_component)(attest_db_t *this, char *comp, bool create); /** - * Set primary key of the software product to be queried + * Set primary key of the functional component to be queried * - * @param pid primary key of software product + * @param fid primary key of functional component * @return TRUE if successful */ - bool (*set_pid)(attest_db_t *this, int pid); + bool (*set_cid)(attest_db_t *this, int fid); + + /** + * Set directory to be queried + * + * @param dir directory + * @param create if TRUE create database entry if it doesn't exist + * @return TRUE if successful + */ + bool (*set_directory)(attest_db_t *this, char *dir, bool create); + + /** + * Set primary key of the directory to be queried + * + * @param did primary key of directory + * @return TRUE if successful + */ + bool (*set_did)(attest_db_t *this, int did); /** * Set measurement file to be queried @@ -70,36 +87,36 @@ struct attest_db_t { /** * Set functional component to be queried * - * @param comp functional component + * @param key AIK * @param create if TRUE create database entry if it doesn't exist * @return TRUE if successful */ - bool (*set_component)(attest_db_t *this, char *comp, bool create); + bool (*set_key)(attest_db_t *this, char *key, bool create); /** - * Set primary key of the functional component to be queried + * Set primary key of the AIK to be queried * - * @param fid primary key of functional component + * @param kid primary key of AIK * @return TRUE if successful */ - bool (*set_cid)(attest_db_t *this, int fid); + bool (*set_kid)(attest_db_t *this, int kid); /** - * Set directory to be queried + * Set software product to be queried * - * @param dir directory + * @param product software product * @param create if TRUE create database entry if it doesn't exist * @return TRUE if successful */ - bool (*set_directory)(attest_db_t *this, char *dir, bool create); + bool (*set_product)(attest_db_t *this, char *product, bool create); /** - * Set primary key of the directory to be queried + * Set primary key of the software product to be queried * - * @param did primary key of directory + * @param pid primary key of software product * @return TRUE if successful */ - bool (*set_did)(attest_db_t *this, int did); + bool (*set_pid)(attest_db_t *this, int pid); /** * Set measurement hash algorithm @@ -109,6 +126,14 @@ struct attest_db_t { 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 */ void (*list_products)(attest_db_t *this); @@ -124,11 +149,21 @@ struct attest_db_t { 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 */ 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 */ bool (*add)(attest_db_t *this); diff --git a/src/libpts/plugins/imv_attestation/attest_usage.c b/src/libpts/plugins/imv_attestation/attest_usage.c index 964e10084..952b88b89 100644 --- a/src/libpts/plugins/imv_attestation/attest_usage.c +++ b/src/libpts/plugins/imv_attestation/attest_usage.c @@ -24,16 +24,14 @@ void usage(void) { printf("\ 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\ ipsec attest --files [--product <name>|--pid <id>]\n\ Show a list of files with a software product name or\n\ its primary key as an optional selector.\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\ Show a list of supported software products with a file path or\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\ its primary key as an optional selector.\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\ Add a file, directory, product or component entry\n\ Component <cfn> entries must be of the form <vendor_id>/<name>-<qualifier>\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\ - 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\ 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\ + \n\ + ipsec attest --del --key <digest>|--kid <id>\n\ + Delete an AIK entry referenced either by value or primary key\n\ \n"); } diff --git a/src/libpts/plugins/imv_attestation/data.sql b/src/libpts/plugins/imv_attestation/data.sql index cc580bce0..20a8e40f5 100644 --- a/src/libpts/plugins/imv_attestation/data.sql +++ b/src/libpts/plugins/imv_attestation/data.sql @@ -176,26 +176,6 @@ INSERT INTO files ( 0, '/etc/tnc_config' ); -/* Components */ - -INSERT INTO components ( - vendor_id, name, qualifier -) VALUES ( - 36906, 1, 33 /* ITA TGRUB */ -); - -INSERT INTO components ( - vendor_id, name, qualifier -) VALUES ( - 36906, 2, 33 /* ITA TBOOT */ -); - -INSERT INTO components ( - vendor_id, name, qualifier -) VALUES ( - 36906, 3, 33 /* ITA IMA */ -); - /* Product-File */ INSERT INTO product_file ( @@ -408,26 +388,6 @@ INSERT INTO product_file ( 7, 22, 1 ); -/* Product Component */ - -INSERT INTO product_component ( - product, component, depth, seq_no -) VALUES ( - 4, 2, 0, 1 -); - -INSERT INTO product_component ( - product, component, depth, seq_no -) VALUES ( - 7, 3, 0, 1 -); - -INSERT INTO product_component ( - product, component, depth, seq_no -) VALUES ( - 7, 2, 0, 2 -); - /* File Hashes */ INSERT INTO file_hashes ( @@ -1295,789 +1255,837 @@ INSERT INTO file_hashes ( 20, 7, 7, 8192, X'84200bd318bb022915150842ddf4002e061ef593604ad0d07021dc662cc40bfa749cce084ddf25d0e5137f6380f613d8' ); +/* AIKs */ + +INSERT INTO keys ( + keyid, owner +) VALUES ( + X'b772a6730776b9f028e5adfccd40b55c320a13b6', 'Andreas, merthyr (Fujitsu Siemens Lifebook S6420)' +); + +/* Components */ + +INSERT INTO components ( + vendor_id, name, qualifier +) VALUES ( + 36906, 1, 33 /* ITA TGRUB */ +); + +INSERT INTO components ( + vendor_id, name, qualifier +) VALUES ( + 36906, 2, 33 /* ITA TBOOT */ +); + +INSERT INTO components ( + vendor_id, name, qualifier +) VALUES ( + 36906, 3, 33 /* ITA IMA */ +); + +/* AIK Component */ + +INSERT INTO key_component ( + key, component, depth, seq_no +) VALUES ( + 2, 2, 0, 1 +); + +INSERT INTO key_component ( + key, component, depth, seq_no +) VALUES ( + 1, 3, 0, 1 +); + +INSERT INTO key_component ( + key, component, depth, seq_no +) VALUES ( + 1, 2, 0, 2 +); + /* Component Hashes */ /* ITA TBOOT Functional Component */ INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 2, 4, 1, 17, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902' + 2, 2, 1, 17, 32768, X'9704353630674bfe21b86b64a7b0f99c297cf902' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 2, 4, 2, 18, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0' + 2, 2, 2, 18, 32768, X'8397d8048ee36d7955e38da16fc33e86ef61d6b0' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 2, 7, 1, 17, 32768, X'd537d437f058136eb3d7be517dbe7647b623c619' + 2, 1, 1, 17, 32768, X'd537d437f058136eb3d7be517dbe7647b623c619' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 2, 7, 2, 18, 32768, X'160d2b04d11eb225fb148615b699081869e15b6c' + 2, 1, 2, 18, 32768, X'160d2b04d11eb225fb148615b699081869e15b6c' ); /* ITA IMA Functional Component */ INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 1, 0, 32768, X'4d894eef0ae7cb124740df4f6c5c35aa0fe7dae8' + 3, 1, 1, 0, 32768, X'4d894eef0ae7cb124740df4f6c5c35aa0fe7dae8' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 2, 0, 32768, X'f2c846e7f335f7b9e9dd0a44f48c48e1986750c7' + 3, 1, 2, 0, 32768, X'f2c846e7f335f7b9e9dd0a44f48c48e1986750c7' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 3, 0, 32768, X'db0b68f3ad06b5c0c35deb56af22b8f0bc23ea50' + 3, 1, 3, 0, 32768, X'db0b68f3ad06b5c0c35deb56af22b8f0bc23ea50' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 4, 0, 32768, X'a662680c8564f92cf20c5857d781ed3f0806da5d' + 3, 1, 4, 0, 32768, X'a662680c8564f92cf20c5857d781ed3f0806da5d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 5, 0, 32768, X'10bfa817da3a9e5760fbe78f216502e8ca4f94ef' + 3, 1, 5, 0, 32768, X'10bfa817da3a9e5760fbe78f216502e8ca4f94ef' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 6, 0, 32768, X'd0e1af1be845f570e44612613c4ddf3f08996151' + 3, 1, 6, 0, 32768, X'd0e1af1be845f570e44612613c4ddf3f08996151' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 7, 0, 32768, X'f05553c39e8130c7bb5db6cd6a6bf627311a9b01' + 3, 1, 7, 0, 32768, X'f05553c39e8130c7bb5db6cd6a6bf627311a9b01' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 8, 0, 32768, X'96ef1ad4efc5be2b894a12e5bffddcd496044a08' + 3, 1, 8, 0, 32768, X'96ef1ad4efc5be2b894a12e5bffddcd496044a08' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 9, 0, 32768, X'e9055f2050b99b9127b6feef3164cb8ead8eb2eb' + 3, 1, 9, 0, 32768, X'e9055f2050b99b9127b6feef3164cb8ead8eb2eb' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 10, 0, 32768, X'6f8150aa3423544ea59ea10025993e660568cc08' + 3, 1, 10, 0, 32768, X'6f8150aa3423544ea59ea10025993e660568cc08' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 11, 0, 32768, X'f843e55c9061fec89f2aeb369a74b73fe8eb09e4' + 3, 1, 11, 0, 32768, X'f843e55c9061fec89f2aeb369a74b73fe8eb09e4' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 12, 0, 32768, X'1d1efd1cb89be96f8fdf20ee0b67a89670659208' + 3, 1, 12, 0, 32768, X'1d1efd1cb89be96f8fdf20ee0b67a89670659208' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 13, 0, 32768, X'f907598ec6fcc5779ff9091ba0925c1d58500352' + 3, 1, 13, 0, 32768, X'f907598ec6fcc5779ff9091ba0925c1d58500352' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 14, 0, 32768, X'42f32d6fba099b0eea2e9a480dc8d4482e20412e' + 3, 1, 14, 0, 32768, X'42f32d6fba099b0eea2e9a480dc8d4482e20412e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 15, 0, 32768, X'e8a7cd52522ebacf4637a2b875494cda1c26bd8c' + 3, 1, 15, 0, 32768, X'e8a7cd52522ebacf4637a2b875494cda1c26bd8c' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 16, 0, 32768, X'd62d2c550fd06cae76f3e9c4d63f5fc22e34d4fe' + 3, 1, 16, 0, 32768, X'd62d2c550fd06cae76f3e9c4d63f5fc22e34d4fe' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 17, 0, 32768, X'dc1293a87cab43024a4eaeb684a0186e33dacfe3' + 3, 1, 17, 0, 32768, X'dc1293a87cab43024a4eaeb684a0186e33dacfe3' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 18, 0, 32768, X'03df488f642a9614ed718bf149fb7289d124189a' + 3, 1, 18, 0, 32768, X'03df488f642a9614ed718bf149fb7289d124189a' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 19, 0, 32768, X'46f1426433c57ee44b5593584308f8b7ac414e17' + 3, 1, 19, 0, 32768, X'46f1426433c57ee44b5593584308f8b7ac414e17' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 20, 0, 32768, X'1a837850cff01cd311948abd611174fa5699804b' + 3, 1, 20, 0, 32768, X'1a837850cff01cd311948abd611174fa5699804b' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 21, 0, 32768, X'1c15052b28ac97e6e1cd0b4671fe75607c07de02' + 3, 1, 21, 0, 32768, X'1c15052b28ac97e6e1cd0b4671fe75607c07de02' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 22, 0, 32768, X'1839bc8b6cd9351565a6bacb57f0e35562962cba' + 3, 1, 22, 0, 32768, X'1839bc8b6cd9351565a6bacb57f0e35562962cba' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 23, 0, 32768, X'f428189580a77b142b3de6cd3c183cb0a24dba6f' + 3, 1, 23, 0, 32768, X'f428189580a77b142b3de6cd3c183cb0a24dba6f' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 24, 0, 32768, X'f9b7302c9212a5398057ddea9c7506b265c3276f' + 3, 1, 24, 0, 32768, X'f9b7302c9212a5398057ddea9c7506b265c3276f' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 25, 0, 32768, X'3af5d2929b9606b94b404a45deed9a9d673f49b7' + 3, 1, 25, 0, 32768, X'3af5d2929b9606b94b404a45deed9a9d673f49b7' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 26, 0, 32768, X'51a7df78bd7a23399b2824ec053f2abe5e4ee049' + 3, 1, 26, 0, 32768, X'51a7df78bd7a23399b2824ec053f2abe5e4ee049' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 27, 0, 32768, X'2a3675f5efce9151670e9d4ec41e2edf4708d336' + 3, 1, 27, 0, 32768, X'2a3675f5efce9151670e9d4ec41e2edf4708d336' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 28, 0, 32768, X'a0cc14b4fde29d7251673af434b2ab246e5acf5a' + 3, 1, 28, 0, 32768, X'a0cc14b4fde29d7251673af434b2ab246e5acf5a' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 29, 0, 32768, X'5932b35ba45894e65d6aa1afbe2101f677e17000' + 3, 1, 29, 0, 32768, X'5932b35ba45894e65d6aa1afbe2101f677e17000' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 30, 0, 32768, X'ee12ad673d19d8f436ea7832e64935a0ddf9930e' + 3, 1, 30, 0, 32768, X'ee12ad673d19d8f436ea7832e64935a0ddf9930e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 31, 0, 32768, X'7bd9b4947ae9b600e6a2d61ead80104d878bb9d2' + 3, 1, 31, 0, 32768, X'7bd9b4947ae9b600e6a2d61ead80104d878bb9d2' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 32, 0, 32768, X'849c60fc7b366717aea2295a37b341e40626dd28' + 3, 1, 32, 0, 32768, X'849c60fc7b366717aea2295a37b341e40626dd28' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 33, 0, 32768, X'cdd448834760041cc30edd09f41ae36cbf9459ef' + 3, 1, 33, 0, 32768, X'cdd448834760041cc30edd09f41ae36cbf9459ef' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 34, 0, 32768, X'9471225809633ae61f2693711cd878ba2ac59ef9' + 3, 1, 34, 0, 32768, X'9471225809633ae61f2693711cd878ba2ac59ef9' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 35, 0, 32768, X'4aaa26a4d1389b2400138269d3415bb492cc4312' + 3, 1, 35, 0, 32768, X'4aaa26a4d1389b2400138269d3415bb492cc4312' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 36, 0, 32768, X'a08b0c957c8f741e273e8aa9a88d87b32b860228' + 3, 1, 36, 0, 32768, X'a08b0c957c8f741e273e8aa9a88d87b32b860228' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 37, 0, 32768, X'7ecbc26a2272256969e4c626998570c7e013be9c' + 3, 1, 37, 0, 32768, X'7ecbc26a2272256969e4c626998570c7e013be9c' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 38, 0, 32768, X'12dcf52c5a92b64dd5113031379f27b9f42d5c49' + 3, 1, 38, 0, 32768, X'12dcf52c5a92b64dd5113031379f27b9f42d5c49' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 39, 0, 32768, X'ca1b8cc8e8ee8b209fc7b55656c3f6ac0b8f86fd' + 3, 1, 39, 0, 32768, X'ca1b8cc8e8ee8b209fc7b55656c3f6ac0b8f86fd' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 40, 0, 32768, X'8566865ae43d19574e85f9f3b6376715ffb3c707' + 3, 1, 40, 0, 32768, X'8566865ae43d19574e85f9f3b6376715ffb3c707' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 41, 0, 32768, X'39c9fda07d57fc185b37bac70ba1068d6e7c41d3' + 3, 1, 41, 0, 32768, X'39c9fda07d57fc185b37bac70ba1068d6e7c41d3' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 42, 0, 32768, X'96a2c8b6caf11da5a37b41706217d4e94bb627c0' + 3, 1, 42, 0, 32768, X'96a2c8b6caf11da5a37b41706217d4e94bb627c0' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 43, 0, 32768, X'6ee8c5a500af82a1fdf42e5122196fad4f2bbc06' + 3, 1, 43, 0, 32768, X'6ee8c5a500af82a1fdf42e5122196fad4f2bbc06' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 44, 0, 32768, X'd2f71dff59d0ab86d0ada6ea288227602d6cf371' + 3, 1, 44, 0, 32768, X'd2f71dff59d0ab86d0ada6ea288227602d6cf371' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 45, 0, 32768, X'095c8df0b106947e2c62a4458b13f38c6fc4f982' + 3, 1, 45, 0, 32768, X'095c8df0b106947e2c62a4458b13f38c6fc4f982' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 46, 0, 32768, X'706071d37157e1030900df60e6efaf897fbab1ec' + 3, 1, 46, 0, 32768, X'706071d37157e1030900df60e6efaf897fbab1ec' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 47, 0, 32768, X'97f093c5ab5e2baf9b6f1473b631d3db2595fe99' + 3, 1, 47, 0, 32768, X'97f093c5ab5e2baf9b6f1473b631d3db2595fe99' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 48, 0, 32768, X'c12dd08ffbb4c09e3c282dd7f94cdcc9148ab866' + 3, 1, 48, 0, 32768, X'c12dd08ffbb4c09e3c282dd7f94cdcc9148ab866' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 49, 0, 32768, X'fb3df3be6d847db26e07eb61312bdc533bda53d2' + 3, 1, 49, 0, 32768, X'fb3df3be6d847db26e07eb61312bdc533bda53d2' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 50, 0, 32768, X'88195da5656b80c68bd3e131fb673b197281c2b0' + 3, 1, 50, 0, 32768, X'88195da5656b80c68bd3e131fb673b197281c2b0' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 51, 0, 32768, X'28353744f0fab757b1a870de007b6c8821d4723e' + 3, 1, 51, 0, 32768, X'28353744f0fab757b1a870de007b6c8821d4723e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 52, 0, 32768, X'9338b619160d4fb1a844acc95b0556b3d6109a77' + 3, 1, 52, 0, 32768, X'9338b619160d4fb1a844acc95b0556b3d6109a77' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 53, 0, 32768, X'cd7f42895c6e4f9752f8b34184059d7ad4e5e6ce' + 3, 1, 53, 0, 32768, X'cd7f42895c6e4f9752f8b34184059d7ad4e5e6ce' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 54, 0, 32768, X'da5611278bf6855a44e5b1b5d62c76822a81674d' + 3, 1, 54, 0, 32768, X'da5611278bf6855a44e5b1b5d62c76822a81674d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 55, 0, 32768, X'eb4148c57806114b755416ba96b282fcc99ac2d1' + 3, 1, 55, 0, 32768, X'eb4148c57806114b755416ba96b282fcc99ac2d1' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 56, 0, 32768, X'5e05f61508a391480dc83f741920a5de059546bc' + 3, 1, 56, 0, 32768, X'5e05f61508a391480dc83f741920a5de059546bc' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 57, 0, 32768, X'a23b279883915b0dc3313081924366ea5e75bdc1' + 3, 1, 57, 0, 32768, X'a23b279883915b0dc3313081924366ea5e75bdc1' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 58, 2, 32768, X'ef7511b5248557ae637f46b552f8af59020f2b00' + 3, 1, 58, 2, 32768, X'ef7511b5248557ae637f46b552f8af59020f2b00' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 59, 2, 32768, X'6240c588a2d7740f5c2c9523bff7d98334998d77' + 3, 1, 59, 2, 32768, X'6240c588a2d7740f5c2c9523bff7d98334998d77' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 60, 2, 32768, X'808ce28868d844d547e0c2cc4271c14be2a568b6' + 3, 1, 60, 2, 32768, X'808ce28868d844d547e0c2cc4271c14be2a568b6' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 61, 2, 32768, X'd736a206033ecbefc09e909f0d2d72c38d49d50b' + 3, 1, 61, 2, 32768, X'd736a206033ecbefc09e909f0d2d72c38d49d50b' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 62, 2, 32768, X'387a7087c3159f7d0a6388d722c200a599b4703b' + 3, 1, 62, 2, 32768, X'387a7087c3159f7d0a6388d722c200a599b4703b' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 63, 2, 32768, X'b6a679dda488042eee3cf9a525a9ae88b9514229' + 3, 1, 63, 2, 32768, X'b6a679dda488042eee3cf9a525a9ae88b9514229' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 64, 2, 32768, X'693b89dc96682f85b389208ec052f4853fd971eb' + 3, 1, 64, 2, 32768, X'693b89dc96682f85b389208ec052f4853fd971eb' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 65, 2, 32768, X'e4b83a6888c69eeb1c65c7ff50ee39897ca51008' + 3, 1, 65, 2, 32768, X'e4b83a6888c69eeb1c65c7ff50ee39897ca51008' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 66, 2, 32768, X'9e0735ad94f4d10faa43f75d02c4edb9b7eb91d4' + 3, 1, 66, 2, 32768, X'9e0735ad94f4d10faa43f75d02c4edb9b7eb91d4' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 67, 2, 32768, X'881dd3cb2f1f0e3323bf8c5586dfaba2ffcb1a55' + 3, 1, 67, 2, 32768, X'881dd3cb2f1f0e3323bf8c5586dfaba2ffcb1a55' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 68, 2, 32768, X'6461d3771999c3a4b3c15bf4e38da30b91bc1b17' + 3, 1, 68, 2, 32768, X'6461d3771999c3a4b3c15bf4e38da30b91bc1b17' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 69, 6, 32768, X'fcad787f7771637d659638d92b5eee9385b3d7b9' + 3, 1, 69, 6, 32768, X'fcad787f7771637d659638d92b5eee9385b3d7b9' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 70, 0, 32768, X'4b90d9178efc5cf9a9ddf4f8bcc49008785d76ec' + 3, 1, 70, 0, 32768, X'4b90d9178efc5cf9a9ddf4f8bcc49008785d76ec' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 71, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' + 3, 1, 71, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 72, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' + 3, 1, 72, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 73, 2, 32768, X'bc3a1d50aaffa207d2e6645228bb4f1cd40c88e0' + 3, 1, 73, 2, 32768, X'bc3a1d50aaffa207d2e6645228bb4f1cd40c88e0' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 74, 2, 32768, X'96ea8b0ccfb43fa6da4e98d8f51609cf8eabd91e' + 3, 1, 74, 2, 32768, X'96ea8b0ccfb43fa6da4e98d8f51609cf8eabd91e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 75, 2, 32768, X'd05ef7250cc103540601fb8956c89c3ba1f47a4e' + 3, 1, 75, 2, 32768, X'd05ef7250cc103540601fb8956c89c3ba1f47a4e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 76, 2, 32768, X'd5c28da6b58a66fba125e99c6b6d0e36a1b18315' + 3, 1, 76, 2, 32768, X'd5c28da6b58a66fba125e99c6b6d0e36a1b18315' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 77, 2, 32768, X'0ba611dd45de9acbe3d0da0d2e478e4aa77ff515' + 3, 1, 77, 2, 32768, X'0ba611dd45de9acbe3d0da0d2e478e4aa77ff515' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 78, 4, 32768, X'9b4d80cfefc7d5576c4d9f224872505896ef2798' + 3, 1, 78, 4, 32768, X'9b4d80cfefc7d5576c4d9f224872505896ef2798' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 79, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' + 3, 1, 79, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 80, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' + 3, 1, 80, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 81, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' + 3, 1, 81, 2, 32768, X'e79e468b1921b2293a80c5917efa6a45c379e810' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 82, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' + 3, 1, 82, 2, 32768, X'be1bdec0aa74b4dcb079943e70528096cca985f8' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 83, 1, 32768, X'230b3bf13c752834decf47f5a86a75582abee51c' + 3, 1, 83, 1, 32768, X'230b3bf13c752834decf47f5a86a75582abee51c' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 84, 1, 32768, X'61f59f7782bb39610dbb6b1f57033c161810a267' + 3, 1, 84, 1, 32768, X'61f59f7782bb39610dbb6b1f57033c161810a267' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 85, 1, 32768, X'c744cac6af7621524fc3a2b0a9a135a32b33c81b' + 3, 1, 85, 1, 32768, X'c744cac6af7621524fc3a2b0a9a135a32b33c81b' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 86, 1, 32768, X'8a7532af1862f9f61ed08d2b92b82a2ecc99c54f' + 3, 1, 86, 1, 32768, X'8a7532af1862f9f61ed08d2b92b82a2ecc99c54f' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 87, 1, 32768, X'ba8fa710d303b3b2a594cba1cb73797c970ffa0b' + 3, 1, 87, 1, 32768, X'ba8fa710d303b3b2a594cba1cb73797c970ffa0b' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 88, 1, 32768, X'a46c5c8b58e67fbe9d3203bae335c0e39f68eff9' + 3, 1, 88, 1, 32768, X'a46c5c8b58e67fbe9d3203bae335c0e39f68eff9' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 89, 1, 32768, X'67476198f63603b84afa235970611cd614560cf2' + 3, 1, 89, 1, 32768, X'67476198f63603b84afa235970611cd614560cf2' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 90, 2, 32768, X'cdf4d79ac0a10d46a1d9d7ec9642883c71f77fc7' + 3, 1, 90, 2, 32768, X'cdf4d79ac0a10d46a1d9d7ec9642883c71f77fc7' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 91, 2, 32768, X'436067385bf6cd43e2f65f8d70d264af8fca876d' + 3, 1, 91, 2, 32768, X'436067385bf6cd43e2f65f8d70d264af8fca876d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 92, 2, 32768, X'4916c4e9f1e91b34bd8acef1f827f0b444bdb858' + 3, 1, 92, 2, 32768, X'4916c4e9f1e91b34bd8acef1f827f0b444bdb858' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 93, 2, 32768, X'c66007c47ea62816006d220bbb8fc9d5681c4cc6' + 3, 1, 93, 2, 32768, X'c66007c47ea62816006d220bbb8fc9d5681c4cc6' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 94, 2, 32768, X'85782c59534d3915298da3da35101891a84be99e' + 3, 1, 94, 2, 32768, X'85782c59534d3915298da3da35101891a84be99e' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 95, 2, 32768, X'335f1897c44fef511bed7eb4394375bc2a36dbc3' + 3, 1, 95, 2, 32768, X'335f1897c44fef511bed7eb4394375bc2a36dbc3' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 96, 2, 32768, X'82ca255a4c2655eca1516b4249dcdd1edb892eef' + 3, 1, 96, 2, 32768, X'82ca255a4c2655eca1516b4249dcdd1edb892eef' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 97, 2, 32768, X'1086445009abbad955b9e915be04ac9afc74567d' + 3, 1, 97, 2, 32768, X'1086445009abbad955b9e915be04ac9afc74567d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 98, 2, 32768, X'18fe7ae42869e2b3b11bf67215ef4f1c2e260251' + 3, 1, 98, 2, 32768, X'18fe7ae42869e2b3b11bf67215ef4f1c2e260251' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 99, 2, 32768, X'061efe921cad309990e63ed35a7b833e2eabfd2f' + 3, 1, 99, 2, 32768, X'061efe921cad309990e63ed35a7b833e2eabfd2f' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 100, 2, 32768, X'aab5803005883807e91538fdc71968edf81f367c' + 3, 1, 100, 2, 32768, X'aab5803005883807e91538fdc71968edf81f367c' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 101, 2, 32768, X'aab5803005883807e91538fdc71968edf81f367c' + 3, 1, 101, 2, 32768, X'aab5803005883807e91538fdc71968edf81f367c' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 102, 2, 32768, X'0ba199b3cd6991a884fe30f40e89d3d603aa5cbd' + 3, 1, 102, 2, 32768, X'0ba199b3cd6991a884fe30f40e89d3d603aa5cbd' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 103, 2, 32768, X'0ba199b3cd6991a884fe30f40e89d3d603aa5cbd' + 3, 1, 103, 2, 32768, X'0ba199b3cd6991a884fe30f40e89d3d603aa5cbd' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 104, 2, 32768, X'2a5aa44e77a223d701a53b0f9af6d13cf8443b2a' + 3, 1, 104, 2, 32768, X'2a5aa44e77a223d701a53b0f9af6d13cf8443b2a' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 105, 2, 32768, X'2a5aa44e77a223d701a53b0f9af6d13cf8443b2a' + 3, 1, 105, 2, 32768, X'2a5aa44e77a223d701a53b0f9af6d13cf8443b2a' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 106, 2, 32768, X'c32ab71e81421207255b2665316a9049ddff3653' + 3, 1, 106, 2, 32768, X'c32ab71e81421207255b2665316a9049ddff3653' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 107, 2, 32768, X'c32ab71e81421207255b2665316a9049ddff3653' + 3, 1, 107, 2, 32768, X'c32ab71e81421207255b2665316a9049ddff3653' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 108, 2, 32768, X'cafaeff88886bf0d07b0a6527341da22c08b609d' + 3, 1, 108, 2, 32768, X'cafaeff88886bf0d07b0a6527341da22c08b609d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 109, 2, 32768, X'cafaeff88886bf0d07b0a6527341da22c08b609d' + 3, 1, 109, 2, 32768, X'cafaeff88886bf0d07b0a6527341da22c08b609d' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 110, 2, 32768, X'68d74b6eacdc3360615744c6aaddb357df9bdbec' + 3, 1, 110, 2, 32768, X'68d74b6eacdc3360615744c6aaddb357df9bdbec' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 111, 2, 32768, X'68d74b6eacdc3360615744c6aaddb357df9bdbec' + 3, 1, 111, 2, 32768, X'68d74b6eacdc3360615744c6aaddb357df9bdbec' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 112, 2, 32768, X'ac254b04f277ca7e887a4141bf5ed0cf62600d10' + 3, 1, 112, 2, 32768, X'ac254b04f277ca7e887a4141bf5ed0cf62600d10' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 113, 2, 32768, X'ac254b04f277ca7e887a4141bf5ed0cf62600d10' + 3, 1, 113, 2, 32768, X'ac254b04f277ca7e887a4141bf5ed0cf62600d10' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 114, 1, 32768, X'4f135c9ee49ca7fbfea079e5d6714802f0405407' + 3, 1, 114, 1, 32768, X'4f135c9ee49ca7fbfea079e5d6714802f0405407' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 115, 0, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 115, 0, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 116, 1, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 116, 1, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 117, 2, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 117, 2, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 118, 3, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 118, 3, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 119, 4, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 119, 4, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 120, 5, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 120, 5, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 121, 6, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 121, 6, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 122, 7, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' + 3, 1, 122, 7, 32768, X'9069ca78e7450a285173431b3e52c5c25299e473' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 123, 4, 32768, X'c1e25c3f6b0dc78d57296aa2870ca6f782ccf80f' + 3, 1, 123, 4, 32768, X'c1e25c3f6b0dc78d57296aa2870ca6f782ccf80f' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 124, 4, 32768, X'67a0a98bc4d6321142895a4d938b342f6959c1a9' + 3, 1, 124, 4, 32768, X'67a0a98bc4d6321142895a4d938b342f6959c1a9' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 125, 4, 32768, X'06d60b3a0dee9bb9beb2f0b04aff2e75bd1d2860' + 3, 1, 125, 4, 32768, X'06d60b3a0dee9bb9beb2f0b04aff2e75bd1d2860' ); INSERT INTO component_hashes ( - component, product, seq_no, pcr, algo, hash + component, key, seq_no, pcr, algo, hash ) VALUES ( - 3, 7, 126, 5, 32768, X'1b87003b6c7d90483713c90100cca3e62392b9bc' + 3, 1, 126, 5, 32768, X'1b87003b6c7d90483713c90100cca3e62392b9bc' ); diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.c b/src/libpts/plugins/imv_attestation/imv_attestation_build.c index fb04ee036..c2447cd9f 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_build.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.c @@ -210,9 +210,9 @@ bool imv_attestation_build(pa_tnc_msg_t *msg, { tcg_pts_attr_req_func_comp_evid_t *attr_cast; enumerator_t *enumerator; - char *platform_info; pts_component_t *comp; pts_comp_func_name_t *comp_name; + chunk_t keyid; int vid, name, qualifier; u_int8_t flags; u_int32_t depth; @@ -221,18 +221,17 @@ bool imv_attestation_build(pa_tnc_msg_t *msg, attestation_state->set_handshake_state(attestation_state, IMV_ATTESTATION_STATE_END); - /* Get Platform and OS of the PTS-IMC */ - platform_info = pts->get_platform_info(pts); - if (!pts_db || !platform_info) + if (!pts->get_aik_keyid(pts, &keyid)) { - DBG1(DBG_IMV, "%s%s%s not available", - (pts_db) ? "" : "pts database", - (!pts_db && !platform_info) ? "and" : "", - (platform_info) ? "" : "platform info"); + break; + } + if (!pts_db) + { + DBG1(DBG_PTS, "pts database not available"); break; } - enumerator = pts_db->create_comp_evid_enumerator(pts_db, platform_info); + enumerator = pts_db->create_comp_evid_enumerator(pts_db, keyid); if (!enumerator) { break; diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c index 5fa76121b..a50810b67 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c @@ -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; certificate_t *aik, *issuer; + public_key_t *public; + chunk_t keyid; enumerator_t *e; 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) { - 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, KEY_ANY, aik->get_issuer(aik), FALSE); while (e->enumerate(e, &issuer)) @@ -285,8 +291,10 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, default: case FAILED: attestation_state->set_measurement_error(attestation_state); - /* fall through to next case */ + comp->destroy(comp); + break; case SUCCESS: + name->log(name, " successfully measured "); comp->destroy(comp); break; case NEED_MORE: diff --git a/src/libpts/plugins/imv_attestation/tables.sql b/src/libpts/plugins/imv_attestation/tables.sql index 564914e78..703557a07 100644 --- a/src/libpts/plugins/imv_attestation/tables.sql +++ b/src/libpts/plugins/imv_attestation/tables.sql @@ -7,14 +7,6 @@ CREATE TABLE files ( 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; CREATE TABLE products ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, @@ -34,15 +26,6 @@ CREATE TABLE 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; CREATE TABLE file_hashes ( file INTEGER NOT NULL, @@ -53,13 +36,47 @@ CREATE TABLE file_hashes ( 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; CREATE TABLE component_hashes ( component INTEGER NOT NULL, - product INTEGER NOT NULL, + key INTEGER NOT NULL, seq_no INTEGER NOT NULL, pcr INTEGER NOT NULL, algo INTEGER NOT NULL, hash BLOB NOT NULL, - PRIMARY KEY(component, product, seq_no, algo) + PRIMARY KEY(component, key, seq_no, algo) ); diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c index a05dc7e5e..808a59580 100644 --- a/src/libpts/pts/components/ita/ita_comp_ima.c +++ b/src/libpts/pts/components/ita/ita_comp_ima.c @@ -17,6 +17,7 @@ #include "ita_comp_ima.h" #include "ita_comp_func_name.h" +#include "libpts.h" #include "pts/components/pts_component.h" #include <debug.h> @@ -31,7 +32,6 @@ #define IMA_SECURITY_DIR "/sys/kernel/security/tpm0/" #define IMA_BIOS_MEASUREMENT_PATH IMA_SECURITY_DIR "binary_bios_measurements" #define IMA_PCR_MAX 8 -#define IMA_SEQUENCE 126 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t; @@ -57,6 +57,11 @@ struct pts_ita_comp_ima_t { u_int32_t depth; /** + * AIK keyid + */ + chunk_t keyid; + + /** * IMA BIOS measurement time */ time_t bios_measurement_time; @@ -67,6 +72,11 @@ struct pts_ita_comp_ima_t { linked_list_t *list; /** + * Expected measurement count + */ + int count; + + /** * Measurement sequence number */ int seq_no; @@ -247,27 +257,50 @@ METHOD(pts_component_t, verify, status_t, pts_comp_evidence_t *evidence) { bool has_pcr_info; - char *platform_info; - u_int32_t extended_pcr; + u_int32_t extended_pcr, vid, name; + enum_name_t *names; pts_meas_algorithms_t algo; pts_pcr_transform_t transform; time_t measurement_time; 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, &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, - platform_info, ++this->seq_no, extended_pcr, algo) != SUCCESS) + this->keyid, ++this->seq_no, extended_pcr, algo) != SUCCESS) { 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, @@ -295,6 +328,7 @@ METHOD(pts_component_t, destroy, void, } this->list->destroy_function(this->list, (void *)free_entry); this->name->destroy(this->name); + free(this->keyid.ptr); free(this); } diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c index 572828ad1..67ad2d432 100644 --- a/src/libpts/pts/components/ita/ita_comp_tboot.c +++ b/src/libpts/pts/components/ita/ita_comp_tboot.c @@ -17,14 +17,12 @@ #include "ita_comp_tboot.h" #include "ita_comp_func_name.h" +#include "libpts.h" #include "pts/components/pts_component.h" -#include "pts/components/pts_comp_evidence.h" #include <debug.h> #include <pen/pen.h> -#define TBOOT_SEQUENCE 2 - typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t; /** @@ -49,11 +47,21 @@ struct pts_ita_comp_tboot_t { u_int32_t depth; /** + * AIK keyid + */ + chunk_t keyid; + + /** * Time of TBOOT measurement */ time_t measurement_time; /** + * Expected measurement count + */ + int count; + + /** * Measurement sequence number */ int seq_no; @@ -144,7 +152,7 @@ METHOD(pts_component_t, measure, status_t, this->measurement_time, measurement); 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, @@ -152,27 +160,50 @@ METHOD(pts_component_t, verify, status_t, pts_comp_evidence_t *evidence) { bool has_pcr_info; - char *platform_info; - u_int32_t extended_pcr; + u_int32_t extended_pcr, vid, name; + enum_name_t *names; pts_meas_algorithms_t algo; pts_pcr_transform_t transform; 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, &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, - platform_info, ++this->seq_no, extended_pcr, algo) != SUCCESS) + this->keyid, ++this->seq_no, extended_pcr, algo) != SUCCESS) { 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, pts_ita_comp_tboot_t *this) { this->name->destroy(this->name); + free(this->keyid.ptr); free(this); } diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index bf5c2bcf7..c30a55719 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -459,6 +459,33 @@ METHOD(pts_t, set_aik, void, 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, 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) { - DBG2(DBG_TNC, "PCR %02d selected for TPM Quote", pcr); result = use_quote2 ? Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr, TSS_PCRS_DIRECTION_RELEASE) : @@ -1510,6 +1536,7 @@ pts_t *pts_create(bool is_imc) .get_pcr_len = _get_pcr_len, .get_aik = _get_aik, .set_aik = _set_aik, + .get_aik_keyid = _get_aik_keyid, .is_path_valid = _is_path_valid, .hash_file = _hash_file, .do_measurements = _do_measurements, diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index 3a40c1e1d..327b1a13d 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -246,6 +246,14 @@ struct pts_t { 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 * * @param path Absolute path diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c index cb2d104f0..d91a408cf 100644 --- a/src/libpts/pts/pts_database.c +++ b/src/libpts/pts/pts_database.c @@ -69,23 +69,6 @@ METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*, 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*, private_pts_database_t *this, char *product, pts_meas_algorithms_t algo, int id, bool is_dir) @@ -114,9 +97,25 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*, 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, 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) { enumerator_t *e; @@ -125,14 +124,14 @@ METHOD(pts_database_t, check_comp_measurement, status_t, e = this->db->query(this->db, "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 " "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_name(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); if (!e) { @@ -144,8 +143,6 @@ METHOD(pts_database_t, check_comp_measurement, status_t, { if (chunk_equals(hash, measurement)) { - DBG2(DBG_PTS, "PCR %2d matching component measurement #%d " - "found in database", pcr, seq_no); status = SUCCESS; break; } @@ -170,6 +167,58 @@ METHOD(pts_database_t, check_comp_measurement, status_t, 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, 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_file_hash_enumerator = _create_file_hash_enumerator, .check_comp_measurement = _check_comp_measurement, + .get_comp_measurement_count = _get_comp_measurement_count, .destroy = _destroy, }, .db = lib->db->create(lib->db, uri), diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h index 3ed0b5bd5..61c00a1e9 100644 --- a/src/libpts/pts/pts_database.h +++ b/src/libpts/pts/pts_database.h @@ -52,15 +52,6 @@ struct pts_database_t { 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 * * @param product Software product (os, vpn client, etc.) @@ -74,21 +65,42 @@ struct pts_database_t { 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 * * @param measurement measurement hash * @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 prc Number of the PCR the measurement was extended into * @param algo Hash algorithm used for measurement * @return return code */ 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); /** + * 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. */ void (*destroy)(pts_database_t *this); |