summaryrefslogtreecommitdiff
path: root/src/libimcv/swid
diff options
context:
space:
mode:
Diffstat (limited to 'src/libimcv/swid')
-rw-r--r--src/libimcv/swid/swid_error.c55
-rw-r--r--src/libimcv/swid/swid_error.h58
-rw-r--r--src/libimcv/swid/swid_inventory.c454
-rw-r--r--src/libimcv/swid/swid_inventory.h84
-rw-r--r--src/libimcv/swid/swid_tag.c102
-rw-r--r--src/libimcv/swid/swid_tag.h70
-rw-r--r--src/libimcv/swid/swid_tag_id.c114
-rw-r--r--src/libimcv/swid/swid_tag_id.h73
8 files changed, 1010 insertions, 0 deletions
diff --git a/src/libimcv/swid/swid_error.c b/src/libimcv/swid/swid_error.c
new file mode 100644
index 000000000..7f3c34476
--- /dev/null
+++ b/src/libimcv/swid/swid_error.c
@@ -0,0 +1,55 @@
+/*
+ * 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 "swid_error.h"
+
+#include <bio/bio_writer.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+
+ENUM(swid_error_code_names, TCG_SWID_ERROR, TCG_SWID_RESPONSE_TOO_LARGE,
+ "SWID Error",
+ "SWID Subscription Denied",
+ "SWID Response Too Large"
+);
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
+ u_int32_t max_attr_size, char *description)
+{
+ bio_writer_t *writer;
+ chunk_t msg_info;
+ pa_tnc_attr_t *attr;
+ pen_type_t error_code;
+
+ error_code = pen_type_create( PEN_TCG, code);
+ writer = bio_writer_create(4);
+ writer->write_uint32(writer, request_id);
+ if (code == TCG_SWID_RESPONSE_TOO_LARGE)
+ {
+ writer->write_uint32(writer, max_attr_size);
+ }
+ if (description)
+ {
+ writer->write_data(writer, chunk_from_str(description));
+ }
+ msg_info = writer->get_buf(writer);
+ attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
+ writer->destroy(writer);
+
+ return attr;
+}
+
diff --git a/src/libimcv/swid/swid_error.h b/src/libimcv/swid/swid_error.h
new file mode 100644
index 000000000..b459ba686
--- /dev/null
+++ b/src/libimcv/swid/swid_error.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * 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.
+ */
+
+/**
+ * @defgroup swid_error swid_error
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_ERROR_H_
+#define SWID_ERROR_H_
+
+typedef enum swid_error_code_t swid_error_code_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+#include <library.h>
+
+
+/**
+ * SWID Error Codes
+ * see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
+ */
+enum swid_error_code_t {
+ TCG_SWID_ERROR = 0x20,
+ TCG_SWID_SUBSCRIPTION_DENIED = 0x21,
+ TCG_SWID_RESPONSE_TOO_LARGE = 0x22
+};
+
+/**
+ * enum name for swid_error_code_t.
+ */
+extern enum_name_t *swid_error_code_names;
+
+/**
+ * Creates a SWID Error Attribute
+ * see section 4.12 of TNC SWID Message and Attributes for IF-M
+ *
+ * @param code SWID error code
+ * @param request SWID request ID
+ * @param max_attr_size Maximum IF-M attribute size (if applicable)
+ * @param description Optional description string or NULL
+ */
+pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request,
+ u_int32_t max_attr_size, char *description);
+
+#endif /** SWID_ERROR_H_ @}*/
diff --git a/src/libimcv/swid/swid_inventory.c b/src/libimcv/swid/swid_inventory.c
new file mode 100644
index 000000000..a49286954
--- /dev/null
+++ b/src/libimcv/swid/swid_inventory.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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 "swid_inventory.h"
+#include "swid_tag.h"
+#include "swid_tag_id.h"
+
+#include <collections/linked_list.h>
+#include <bio/bio_writer.h>
+#include <utils/debug.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <errno.h>
+
+typedef struct private_swid_inventory_t private_swid_inventory_t;
+
+/**
+ * Private data of a swid_inventory_t object.
+ *
+ */
+struct private_swid_inventory_t {
+
+ /**
+ * Public swid_inventory_t interface.
+ */
+ swid_inventory_t public;
+
+ /**
+ * Full SWID tags or just SWID tag IDs
+ */
+ bool full_tags;
+
+ /**
+ * List of SWID tags or tag IDs
+ */
+ linked_list_t *list;
+};
+
+/**
+ * Read SWID tags issued by the swid_generator tool
+ */
+static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
+{
+ swid_tag_t *tag;
+ bio_writer_t *writer;
+ chunk_t tag_encoding, tag_file_path = chunk_empty;
+ bool more_tags = TRUE, last_newline;
+ char line[8192];
+ size_t len;
+
+ while (more_tags)
+ {
+ last_newline = TRUE;
+ writer = bio_writer_create(512);
+ while (TRUE)
+ {
+ if (!fgets(line, sizeof(line), file))
+ {
+ more_tags = FALSE;
+ break;
+ }
+ len = strlen(line);
+
+ if (last_newline && line[0] == '\n')
+ {
+ break;
+ }
+ else
+ {
+ last_newline = (line[len-1] == '\n');
+ writer->write_data(writer, chunk_create(line, len));
+ }
+ }
+
+ tag_encoding = writer->get_buf(writer);
+
+ if (tag_encoding.len > 1)
+ {
+ /* remove trailing newline if present */
+ if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
+ {
+ tag_encoding.len--;
+ }
+ DBG3(DBG_IMC, " %.*s", tag_encoding.len, tag_encoding.ptr);
+
+ tag = swid_tag_create(tag_encoding, tag_file_path);
+ this->list->insert_last(this->list, tag);
+ }
+ writer->destroy(writer);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Read SWID tag or software IDs issued by the swid_generator tool
+ */
+static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
+{
+ swid_tag_id_t *tag_id;
+ chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
+ char line[BUF_LEN];
+
+ while (TRUE)
+ {
+ char *separator;
+ size_t len;
+
+ if (!fgets(line, sizeof(line), file))
+ {
+ return SUCCESS;
+ }
+ len = strlen(line);
+
+ /* remove trailing newline if present */
+ if (len > 0 && line[len - 1] == '\n')
+ {
+ len--;
+ }
+ DBG3(DBG_IMC, " %.*s", len, line);
+
+ separator = strchr(line, '_');
+ if (!separator)
+ {
+ DBG1(DBG_IMC, "separation of regid from unique software ID failed");
+ return FAILED;
+ }
+ tag_creator = chunk_create(line, separator - line);
+ separator++;
+
+ unique_sw_id = chunk_create(separator, len - (separator - line));
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
+ this->list->insert_last(this->list, tag_id);
+ }
+}
+
+static status_t generate_tags(private_swid_inventory_t *this, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full)
+{
+ FILE *file;
+ char command[BUF_LEN];
+ char doc_separator[] = "'\n\n'";
+
+ status_t status = SUCCESS;
+
+ if (targets->get_count(targets) == 0)
+ {
+ /* Assemble the SWID generator command */
+ if (this->full_tags)
+ {
+ snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
+ generator, doc_separator, pretty ? " --pretty" : "",
+ full ? " --full" : "");
+ }
+ else
+ {
+ snprintf(command, BUF_LEN, "%s software-id", generator);
+ }
+
+ /* Open a pipe stream for reading the SWID generator output */
+ file = popen(command, "r");
+ if (!file)
+ {
+ DBG1(DBG_IMC, "failed to run swid_generator command");
+ return NOT_SUPPORTED;
+ }
+
+ if (this->full_tags)
+ {
+ DBG2(DBG_IMC, "SWID tag generation by package manager");
+ status = read_swid_tags(this, file);
+ }
+ else
+ {
+ DBG2(DBG_IMC, "SWID tag ID generation by package manager");
+ status = read_swid_tag_ids(this, file);
+ }
+ pclose(file);
+ }
+ else if (this->full_tags)
+ {
+ swid_tag_id_t *tag_id;
+ enumerator_t *enumerator;
+
+ enumerator = targets->create_enumerator(targets);
+ while (enumerator->enumerate(enumerator, &tag_id))
+ {
+ char software_id[BUF_LEN];
+ chunk_t tag_creator, unique_sw_id;
+
+ tag_creator = tag_id->get_tag_creator(tag_id);
+ unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+ snprintf(software_id, BUF_LEN, "%.*s_%.*s",
+ tag_creator.len, tag_creator.ptr,
+ unique_sw_id.len, unique_sw_id.ptr);
+
+ /* Assemble the SWID generator command */
+ snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
+ generator, software_id, pretty ? " --pretty" : "",
+ full ? " --full" : "");
+
+ /* Open a pipe stream for reading the SWID generator output */
+ file = popen(command, "r");
+ if (!file)
+ {
+ DBG1(DBG_IMC, "failed to run swid_generator command");
+ return NOT_SUPPORTED;
+ }
+ status = read_swid_tags(this, file);
+ pclose(file);
+
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ return status;
+}
+
+static bool collect_tags(private_swid_inventory_t *this, char *pathname,
+ swid_inventory_t *targets)
+{
+ char *rel_name, *abs_name;
+ struct stat st;
+ bool success = FALSE;
+ enumerator_t *enumerator;
+
+ enumerator = enumerator_create_directory(pathname);
+ if (!enumerator)
+ {
+ DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
+ pathname, strerror(errno));
+ return FALSE;
+ }
+ DBG2(DBG_IMC, "entering %s", pathname);
+
+ while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+ {
+ char * start, *stop;
+ chunk_t tag_creator;
+ chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
+
+ if (!strstr(rel_name, "regid."))
+ {
+ continue;
+ }
+ if (S_ISDIR(st.st_mode))
+ {
+ /* In case of a targeted request */
+ if (targets->get_count(targets))
+ {
+ enumerator_t *target_enumerator;
+ swid_tag_id_t *tag_id;
+ bool match = FALSE;
+
+ target_enumerator = targets->create_enumerator(targets);
+ while (target_enumerator->enumerate(target_enumerator, &tag_id))
+ {
+ if (chunk_equals(tag_id->get_tag_creator(tag_id),
+ chunk_from_str(rel_name)))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ target_enumerator->destroy(target_enumerator);
+
+ if (!match)
+ {
+ continue;
+ }
+ }
+
+ if (!collect_tags(this, abs_name, targets))
+ {
+ goto end;
+ }
+ continue;
+ }
+
+ /* parse the regid filename into its components */
+ start = rel_name;
+ stop = strchr(start, '_');
+ if (!stop)
+ {
+ DBG1(DBG_IMC, " %s", rel_name);
+ DBG1(DBG_IMC, " '_' separator not found");
+ goto end;
+ }
+ tag_creator = chunk_create(start, stop-start);
+ start = stop + 1;
+
+ stop = strstr(start, ".swidtag");
+ if (!stop)
+ {
+ DBG1(DBG_IMC, " %s", rel_name);
+ DBG1(DBG_IMC, " swidtag postfix not found");
+ goto end;
+ }
+ unique_sw_id = chunk_create(start, stop-start);
+ tag_file_path = chunk_from_str(abs_name);
+
+ /* In case of a targeted request */
+ if (targets->get_count(targets))
+ {
+ chunk_t target_unique_sw_id, target_tag_creator;
+ enumerator_t *target_enumerator;
+ swid_tag_id_t *tag_id;
+ bool match = FALSE;
+
+ target_enumerator = targets->create_enumerator(targets);
+ while (target_enumerator->enumerate(target_enumerator, &tag_id))
+ {
+ target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+ target_tag_creator = tag_id->get_tag_creator(tag_id);
+
+ if (chunk_equals(target_unique_sw_id, unique_sw_id) &&
+ chunk_equals(target_tag_creator, tag_creator))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ target_enumerator->destroy(target_enumerator);
+
+ if (!match)
+ {
+ continue;
+ }
+ }
+ DBG2(DBG_IMC, " %s", rel_name);
+
+ if (this->full_tags)
+ {
+ swid_tag_t *tag;
+ chunk_t *xml_tag;
+
+ xml_tag = chunk_map(abs_name, FALSE);
+ if (!xml_tag)
+ {
+ DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
+ strerror(errno));
+ goto end;
+ }
+
+ tag = swid_tag_create(*xml_tag, tag_file_path);
+ this->list->insert_last(this->list, tag);
+ chunk_unmap(xml_tag);
+ }
+ else
+ {
+ swid_tag_id_t *tag_id;
+
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
+ this->list->insert_last(this->list, tag_id);
+ }
+ }
+ success = TRUE;
+
+end:
+ enumerator->destroy(enumerator);
+ DBG2(DBG_IMC, "leaving %s", pathname);
+
+ return success;
+}
+
+METHOD(swid_inventory_t, collect, bool,
+ private_swid_inventory_t *this, char *directory, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full)
+{
+ /**
+ * Tags are generated by a package manager
+ */
+ generate_tags(this, generator, targets, pretty, full);
+
+ /**
+ * Collect swidtag files by iteratively entering all directories in
+ * the tree under the "directory" path.
+ */
+ return collect_tags(this, directory, targets);
+}
+
+METHOD(swid_inventory_t, add, void,
+ private_swid_inventory_t *this, void *item)
+{
+ this->list->insert_last(this->list, item);
+}
+
+METHOD(swid_inventory_t, get_count, int,
+ private_swid_inventory_t *this)
+{
+ return this->list->get_count(this->list);
+}
+
+METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
+ private_swid_inventory_t *this)
+{
+ return this->list->create_enumerator(this->list);
+}
+
+METHOD(swid_inventory_t, destroy, void,
+ private_swid_inventory_t *this)
+{
+ if (this->full_tags)
+ {
+ this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
+ }
+ else
+ {
+ this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
+ }
+ free(this);
+}
+
+/**
+ * See header
+ */
+swid_inventory_t *swid_inventory_create(bool full_tags)
+{
+ private_swid_inventory_t *this;
+
+ INIT(this,
+ .public = {
+ .collect = _collect,
+ .add = _add,
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .full_tags = full_tags,
+ .list = linked_list_create(),
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/swid/swid_inventory.h b/src/libimcv/swid/swid_inventory.h
new file mode 100644
index 000000000..04029070e
--- /dev/null
+++ b/src/libimcv/swid/swid_inventory.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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.
+ */
+
+/**
+ * @defgroup swid_inventory swid_inventory
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_INVENTORY_H_
+#define SWID_INVENTORY_H_
+
+#include <library.h>
+
+/* Maximum size of a SWID Tag Inventory: 100 MB */
+#define SWID_MAX_ATTR_SIZE 100000000
+
+typedef struct swid_inventory_t swid_inventory_t;
+
+/**
+ * Class managing SWID tag inventory
+ */
+struct swid_inventory_t {
+
+ /**
+ * Collect the SWID tags stored on the endpoint
+ *
+ * @param directory SWID directory path
+ * @param generator Path to SWID generator
+ * @param targets List of target tag IDs
+ * @param pretty Generate indented XML SWID tags
+ * @param full Include file information in SWID tags
+ * @return TRUE if successful
+ */
+ bool (*collect)(swid_inventory_t *this, char *directory, char *generator,
+ swid_inventory_t *targets, bool pretty, bool full);
+
+ /**
+ * Collect the SWID tags stored on the endpoint
+ *
+ * @param item SWID tag or tag ID to be added
+ */
+ void (*add)(swid_inventory_t *this, void *item);
+
+ /**
+ * Get the number of collected SWID tags
+ *
+ * @return Number of collected SWID tags
+ */
+ int (*get_count)(swid_inventory_t *this);
+
+ /**
+ * Create a SWID tag inventory enumerator
+ *
+ * @return Enumerator returning either tag ID or full tag
+ */
+ enumerator_t* (*create_enumerator)(swid_inventory_t *this);
+
+ /**
+ * Destroys a swid_inventory_t object.
+ */
+ void (*destroy)(swid_inventory_t *this);
+
+};
+
+/**
+ * Creates a swid_inventory_t object
+ *
+ * @param full_tags TRUE if full tags, FALSE if tag IDs only
+ */
+swid_inventory_t* swid_inventory_create(bool full_tags);
+
+#endif /** SWID_INVENTORY_H_ @}*/
diff --git a/src/libimcv/swid/swid_tag.c b/src/libimcv/swid/swid_tag.c
new file mode 100644
index 000000000..c77c75700
--- /dev/null
+++ b/src/libimcv/swid/swid_tag.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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 "swid_tag.h"
+
+typedef struct private_swid_tag_t private_swid_tag_t;
+
+/**
+ * Private data of a swid_tag_t object.
+ *
+ */
+struct private_swid_tag_t {
+
+ /**
+ * Public swid_tag_t interface.
+ */
+ swid_tag_t public;
+
+ /**
+ * UTF-8 XML encoding of SWID tag
+ */
+ chunk_t encoding;
+
+ /**
+ * Optional Tag Identifier Instance ID
+ */
+ chunk_t instance_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(swid_tag_t, get_encoding, chunk_t,
+ private_swid_tag_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(swid_tag_t, get_instance_id, chunk_t,
+ private_swid_tag_t *this)
+{
+ return this->instance_id;
+}
+
+METHOD(swid_tag_t, get_ref, swid_tag_t*,
+ private_swid_tag_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(swid_tag_t, destroy, void,
+ private_swid_tag_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->encoding.ptr);
+ free(this->instance_id.ptr);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t instance_id)
+{
+ private_swid_tag_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .get_instance_id = _get_instance_id,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .encoding = chunk_clone(encoding),
+ .ref = 1,
+ );
+
+ if (instance_id.len > 0)
+ {
+ this->instance_id = chunk_clone(instance_id);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/swid/swid_tag.h b/src/libimcv/swid/swid_tag.h
new file mode 100644
index 000000000..22c14b1aa
--- /dev/null
+++ b/src/libimcv/swid/swid_tag.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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.
+ */
+
+/**
+ * @defgroup swid_tag swid_tag
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_TAG_H_
+#define SWID_TAG_H_
+
+#include <library.h>
+
+typedef struct swid_tag_t swid_tag_t;
+
+
+/**
+ * Class storing a SWID Tag
+ */
+struct swid_tag_t {
+
+ /**
+ * Get UTF-8 XML encoding of SWID tag
+ *
+ * @return XML encoding of SWID tag
+ */
+ chunk_t (*get_encoding)(swid_tag_t *this);
+
+ /**
+ * Get the optional Tag Identifier Instance ID
+ *
+ * @return Optional Tag Identifier Instance ID
+ */
+ chunk_t (*get_instance_id)(swid_tag_t *this);
+
+ /**
+ * Get a new reference to the swid_tag object
+ *
+ * @return this, with an increased refcount
+ */
+ swid_tag_t* (*get_ref)(swid_tag_t *this);
+
+ /**
+ * Destroys a swid_tag_t object.
+ */
+ void (*destroy)(swid_tag_t *this);
+
+};
+
+/**
+ * Creates a swid_tag_t object
+ *
+ * @param encoding XML encoding of SWID tag
+ * @param instance_id Tag Identifier Instance ID or empty chunk
+ */
+swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t instance_id);
+
+#endif /** SWID_TAG_H_ @}*/
diff --git a/src/libimcv/swid/swid_tag_id.c b/src/libimcv/swid/swid_tag_id.c
new file mode 100644
index 000000000..2dc6e3141
--- /dev/null
+++ b/src/libimcv/swid/swid_tag_id.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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 "swid_tag_id.h"
+
+typedef struct private_swid_tag_id_t private_swid_tag_id_t;
+
+/**
+ * Private data of a swid_tag_id_t object.
+ *
+ */
+struct private_swid_tag_id_t {
+
+ /**
+ * Public swid_tag_id_t interface.
+ */
+ swid_tag_id_t public;
+
+ /**
+ * Tag Creator
+ */
+ chunk_t tag_creator;
+
+ /**
+ * Unique Software ID
+ */
+ chunk_t unique_sw_id;
+
+ /**
+ * Optional Tag Identifier Instance ID
+ */
+ chunk_t instance_id;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
+ private_swid_tag_id_t *this)
+{
+ return this->tag_creator;
+}
+
+METHOD(swid_tag_id_t, get_unique_sw_id, chunk_t,
+ private_swid_tag_id_t *this, chunk_t *instance_id)
+{
+ if (instance_id)
+ {
+ *instance_id = this->instance_id;
+ }
+ return this->unique_sw_id;
+}
+
+METHOD(swid_tag_id_t, get_ref, swid_tag_id_t*,
+ private_swid_tag_id_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(swid_tag_id_t, destroy, void,
+ private_swid_tag_id_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->tag_creator.ptr);
+ free(this->unique_sw_id.ptr);
+ free(this->instance_id.ptr);
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
+ chunk_t instance_id)
+{
+ private_swid_tag_id_t *this;
+
+ INIT(this,
+ .public = {
+ .get_tag_creator = _get_tag_creator,
+ .get_unique_sw_id = _get_unique_sw_id,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .tag_creator = chunk_clone(tag_creator),
+ .unique_sw_id = chunk_clone(unique_sw_id),
+ .ref = 1,
+ );
+
+ if (instance_id.len > 0)
+ {
+ this->instance_id = chunk_clone(instance_id);
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/swid/swid_tag_id.h b/src/libimcv/swid/swid_tag_id.h
new file mode 100644
index 000000000..a2be290ae
--- /dev/null
+++ b/src/libimcv/swid/swid_tag_id.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * 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.
+ */
+
+/**
+ * @defgroup swid_tag_id swid_tag_id
+ * @{ @ingroup libimcv_swid
+ */
+
+#ifndef SWID_TAG_ID_H_
+#define SWID_TAG_ID_H_
+
+#include <library.h>
+
+typedef struct swid_tag_id_t swid_tag_id_t;
+
+
+/**
+ * Class storing a SWID Tag ID
+ */
+struct swid_tag_id_t {
+
+ /**
+ * Get the Tag Creator
+ *
+ * @return Tag Creator
+ */
+ chunk_t (*get_tag_creator)(swid_tag_id_t *this);
+
+ /**
+ * Get the Unique Software ID and optional Tag File Path
+ *
+ * @param instance_id Optional Tag Identifier Instance ID
+ * @return Unique Software ID
+ */
+ chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *instance_id);
+
+ /**
+ * Get a new reference to the swid_tag_id object
+ *
+ * @return this, with an increased refcount
+ */
+ swid_tag_id_t* (*get_ref)(swid_tag_id_t *this);
+
+ /**
+ * Destroys a swid_tag_id_t object.
+ */
+ void (*destroy)(swid_tag_id_t *this);
+
+};
+
+/**
+ * Creates a swid_tag_id_t object
+ *
+ * @param tag_creator Tag Creator
+ * @param unique_sw_id Unique Software ID
+ * @param instance_id Tag Identifier Instance ID or empty chunk
+ */
+swid_tag_id_t* swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
+ chunk_t instance_id);
+
+#endif /** SWID_TAG_ID_H_ @}*/