diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libpts/pts/pts_database.c | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libpts/pts/pts_database.c')
-rw-r--r-- | src/libpts/pts/pts_database.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c new file mode 100644 index 000000000..282755c0a --- /dev/null +++ b/src/libpts/pts/pts_database.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2011 Sansar Choinyambuu + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pts_database.h" + +#include <debug.h> +#include <crypto/hashers/hasher.h> + + +typedef struct private_pts_database_t private_pts_database_t; + +/** + * Private data of a pts_database_t object. + * + */ +struct private_pts_database_t { + + /** + * Public pts_database_t interface. + */ + pts_database_t public; + + /** + * database instance + */ + database_t *db; + +}; + +METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*, + private_pts_database_t *this, char *product) +{ + enumerator_t *e; + + /* look for all entries belonging to a product in the files table */ + e = this->db->query(this->db, + "SELECT f.id, f.type, f.path FROM files AS f " + "JOIN product_file AS pf ON f.id = pf.file " + "JOIN products AS p ON p.id = pf.product " + "WHERE p.name = ? AND pf.measurement = 1", + DB_TEXT, product, DB_INT, DB_INT, DB_TEXT); + return e; +} + +METHOD(pts_database_t, create_file_meta_enumerator, enumerator_t*, + private_pts_database_t *this, char *product) +{ + enumerator_t *e; + + /* look for all entries belonging to a product in the files table */ + e = this->db->query(this->db, + "SELECT f.type, f.path FROM files AS f " + "JOIN product_file AS pf ON f.id = pf.file " + "JOIN products AS p ON p.id = pf.product " + "WHERE p.name = ? AND pf.metadata = 1", + DB_TEXT, product, DB_INT, DB_TEXT); + 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) +{ + enumerator_t *e; + + if (is_dir) + { + e = this->db->query(this->db, + "SELECT f.path, fh.hash FROM file_hashes AS fh " + "JOIN files AS f ON fh.file = f.id " + "JOIN products AS p ON fh.product = p.id " + "WHERE p.name = ? AND fh.directory = ? AND fh.algo = ? " + "ORDER BY f.path", + DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); + } + else + { + e = this->db->query(this->db, + "SELECT f.path, fh.hash FROM file_hashes AS fh " + "JOIN files AS f ON fh.file = f.id " + "JOIN products AS p ON fh.product = p.id " + "WHERE p.name = ? AND fh.file = ? AND fh.algo = ?", + DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB); + } + return e; +} + +METHOD(pts_database_t, check_aik_keyid, status_t, + private_pts_database_t *this, chunk_t keyid, int *kid) +{ + enumerator_t *e; + + /* If the AIK is registered get the primary key */ + 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 FAILED; + } + if (!e->enumerate(e, kid)) + { + DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid); + e->destroy(e); + return FAILED; + } + e->destroy(e); + + return SUCCESS; +} + +METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*, + private_pts_database_t *this, int kid) +{ + enumerator_t *e; + + /* look for all entries belonging to an AIK 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 " + "WHERE kc.key = ? ORDER BY kc.seq_no", + DB_INT, kid, 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, int cid, int kid, + int seq_no, int pcr, pts_meas_algorithms_t algo) +{ + enumerator_t *e; + chunk_t hash; + status_t status = NOT_FOUND; + + e = this->db->query(this->db, + "SELECT hash FROM component_hashes " + "WHERE component = ? AND key = ? " + "AND seq_no = ? AND pcr = ? AND algo = ? ", + DB_INT, cid, DB_INT, kid, DB_INT, seq_no, + DB_INT, pcr, DB_INT, algo, DB_BLOB); + if (!e) + { + DBG1(DBG_PTS, "no database query enumerator returned"); + return FAILED; + } + + while (e->enumerate(e, &hash)) + { + if (chunk_equals(hash, measurement)) + { + status = SUCCESS; + break; + } + else + { + DBG1(DBG_PTS, "PCR %2d no matching component measurement #%d " + "found in database", pcr, seq_no); + DBG1(DBG_PTS, " expected: %#B", &hash); + DBG1(DBG_PTS, " received: %#B", &measurement); + status = FAILED; + break; + } + } + e->destroy(e); + + if (status == NOT_FOUND) + { + DBG1(DBG_PTS, "PCR %2d no measurement #%d " + "found in database", pcr, seq_no); + } + + return status; +} + +METHOD(pts_database_t, insert_comp_measurement, status_t, + private_pts_database_t *this, chunk_t measurement, int cid, int kid, + int seq_no, int pcr, pts_meas_algorithms_t algo) +{ + int id; + + if (this->db->execute(this->db, &id, + "INSERT INTO component_hashes " + "(component, key, seq_no, pcr, algo, hash) " + "VALUES (?, ?, ?, ?, ?, ?)", + DB_INT, cid, DB_INT, kid, DB_INT, seq_no, DB_INT, pcr, + DB_INT, algo, DB_BLOB, measurement) == 1) + { + return SUCCESS; + } + + DBG1(DBG_PTS, "could not insert component measurement into database"); + return FAILED; +} + +METHOD(pts_database_t, delete_comp_measurements, int, + private_pts_database_t *this, int cid, int kid) +{ + return this->db->execute(this->db, NULL, + "DELETE FROM component_hashes " + "WHERE component = ? AND key = ?", + DB_INT, cid, DB_INT, kid); +} + +METHOD(pts_database_t, get_comp_measurement_count, status_t, + private_pts_database_t *this, pts_comp_func_name_t *comp_name, + chunk_t keyid, pts_meas_algorithms_t algo, int *cid, int *kid, int *count) +{ + enumerator_t *e; + status_t status = SUCCESS; + + /* Initialize count */ + *count = 0; + + if (_check_aik_keyid(this, keyid, kid) != SUCCESS) + { + return FAILED; + } + + /* Get the primary key of the Component Functional Name */ + e = this->db->query(this->db, + "SELECT id FROM components " + " WHERE vendor_id = ? AND name = ? AND qualifier = ?", + 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); + if (!e) + { + DBG1(DBG_PTS, "no database query enumerator returned"); + return FAILED; + } + if (!e->enumerate(e, cid)) + { + DBG1(DBG_PTS, "component functional name not found in database"); + e->destroy(e); + return FAILED; + } + 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 " + "WHERE component = ? AND key = ? AND algo = ?", + DB_INT, *cid, DB_INT, *kid, DB_INT, algo, DB_INT); + if (!e) + { + DBG1(DBG_PTS, "no database query enumerator returned"); + return FAILED; + } + if (!e->enumerate(e, count)) + { + DBG1(DBG_PTS, "no component measurement count returned from database"); + status = FAILED; + } + e->destroy(e); + + return status; +} + +METHOD(pts_database_t, destroy, void, + private_pts_database_t *this) +{ + this->db->destroy(this->db); + free(this); +} + +/** + * See header + */ +pts_database_t *pts_database_create(char *uri) +{ + private_pts_database_t *this; + + INIT(this, + .public = { + .create_file_meas_enumerator = _create_file_meas_enumerator, + .create_file_meta_enumerator = _create_file_meta_enumerator, + .create_comp_evid_enumerator = _create_comp_evid_enumerator, + .create_file_hash_enumerator = _create_file_hash_enumerator, + .check_aik_keyid = _check_aik_keyid, + .check_comp_measurement = _check_comp_measurement, + .insert_comp_measurement = _insert_comp_measurement, + .delete_comp_measurements = _delete_comp_measurements, + .get_comp_measurement_count = _get_comp_measurement_count, + .destroy = _destroy, + }, + .db = lib->db->create(lib->db, uri), + ); + + if (!this->db) + { + DBG1(DBG_PTS, + "failed to connect to PTS file measurement database '%s'", uri); + free(this); + return NULL; + } + + return &this->public; +} + |