summaryrefslogtreecommitdiff
path: root/src/libpts/pts/pts_database.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
committerYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
commitb34738ed08c2227300d554b139e2495ca5da97d6 (patch)
tree62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libpts/pts/pts_database.c
parent0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff)
downloadvyos-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.c312
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;
+}
+