ARG_ENABL_SET([monolithic], [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.])
ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.])
ARG_ENABL_SET([unit-tests], [enable unit tests using the check test framework.])
+ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.])
# ===================================
# option to disable default options
CFLAGS="$CFLAGS -include `pwd`/config.h"
+if test x$tkm = xtrue; then
+ AC_PATH_PROG([GPRBUILD], [gprbuild], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
+fi
+
if test x$unit_tests = xtrue; then
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4])
AC_SUBST(CHECK_CFLAGS)
AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
-AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue)
-AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue)
-AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue)
+AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
+AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
+AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers)
AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
AM_CONDITIONAL(UNITTESTS, test x$unit_tests = xtrue)
+AM_CONDITIONAL(USE_TKM, test x$tkm = xtrue)
# ========================
# set global definitions
src/libimcv/plugins/imv_os/Makefile
src/charon/Makefile
src/charon-nm/Makefile
+ src/charon-tkm/Makefile
src/libcharon/Makefile
src/libcharon/plugins/eap_aka/Makefile
src/libcharon/plugins/eap_aka_3gpp2/Makefile
SUBDIRS += checksum
endif
+if USE_TKM
+ SUBDIRS += charon-tkm
+endif
+
EXTRA_DIST = strongswan.conf
install-exec-local :
--- /dev/null
+SRC = $(top_builddir)/src
+
+# includes relative to obj directory
+INCLUDES = \
+ -include $(top_builddir)/config.h \
+ -I../$(SRC)/libstrongswan \
+ -I../$(SRC)/libhydra \
+ -I../$(SRC)/libcharon
+
+LIBLD = \
+ -L$(SRC)/libstrongswan/.libs \
+ -L$(SRC)/libhydra/.libs \
+ -L$(SRC)/libcharon/.libs
+LIBPT = $(SRC)/libstrongswan/.libs:$(SRC)/libhydra/.libs:$(SRC)/libcharon/.libs
+LIBFL = -lstrongswan -lhydra -lcharon
+
+DEFS += -DPLUGINS=\""$(PLUGINS)\"" -DIPSEC_PIDDIR=\"${piddir}\"
+
+BUILD_OPTS = \
+ -cargs $(INCLUDES) $(DEFS) \
+ -largs $(LIBLD) $(LIBFL)
+
+# plugins to enable
+PLUGINS = \
+ aes \
+ constraints \
+ gmp \
+ hmac \
+ kernel-netlink \
+ nonce \
+ pem \
+ pkcs1 \
+ pkcs8 \
+ random \
+ sha1 \
+ sha2 \
+ stroke \
+ socket-default \
+ x509
+
+all: build_charon
+
+build_charon: build_charon.gpr src/charon-tkm.c
+ @$(GPRBUILD) -p $< $(BUILD_OPTS)
+
+build_tests: build_tests.gpr
+ @$(GPRBUILD) -p $< $(BUILD_OPTS) -cargs @CHECK_CFLAGS@ -largs @CHECK_LIBS@
+
+if UNITTESTS
+check: build_tests
+ @LD_LIBRARY_PATH=$(LIBPT) obj/test_runner
+else
+check:
+ @echo "reconfigure with --enable-unit-tests"
+endif
+
+install: build_charon
+ $(INSTALL) -m 755 obj/charon-tkm $(DESTDIR)$(ipsecdir)
+
+clean:
+ rm -rf obj
+
+EXTRA_DIST = build_charon.gpr build_common.gpr build_tests.gpr src tests
--- /dev/null
+with "build_common";
+
+project Build_Charon is
+
+ for Languages use ("C");
+ for Source_Dirs use ("src/**");
+ for Main use ("charon-tkm");
+ for Object_Dir use Build_Common.Obj_Dir;
+
+ package Compiler is
+ for Default_Switches ("c") use Build_Common.C_Compiler_Switches
+ & "-Werror";
+ end Compiler;
+
+end Build_Charon;
--- /dev/null
+with "tkmrpc_client";
+
+project Build_Common is
+
+ for Source_Dirs use ();
+
+ Obj_Dir := "obj";
+ Compiler_Switches := ("-W", "-Wall", "-Wno-unused-parameter");
+
+end Build_Common;
--- /dev/null
+with "build_common";
+
+project Build_Tests is
+
+ for Languages use ("C");
+ for Source_Dirs use ("src/tkm", "tests");
+ for Main use ("test_runner");
+ for Object_Dir use Build_Common.Obj_Dir;
+
+ package Compiler is
+ for Default_Switches ("c") use Build_Common.Compiler_Switches;
+ end Compiler;
+
+end Build_Tests;
--- /dev/null
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <syslog.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <libgen.h>
+
+#include <hydra.h>
+#include <daemon.h>
+
+#include <library.h>
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+
+#include <tkm/client.h>
+
+/**
+ * PID file, in which charon-tkm stores its process id
+ */
+static char *pidfile_name = NULL;
+
+/**
+ * Global reference to PID file (required to truncate, if undeletable)
+ */
+static FILE *pidfile = NULL;
+
+/**
+ * Hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Simple logging hook for library logs, using syslog output
+ */
+static void dbg_syslog(debug_t group, level_t level, char *fmt, ...)
+{
+ if (level <= 1)
+ {
+ char buffer[8192];
+ va_list args;
+
+ va_start(args, fmt);
+ /* write in memory buffer first */
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", debug_names->names[group],
+ buffer);
+ va_end(args);
+ }
+}
+
+/**
+ * Run the daemon and handle unix signals
+ */
+static void run()
+{
+ sigset_t set;
+
+ /* handle SIGINT and SIGTERM in this handler */
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTERM);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ while (TRUE)
+ {
+ int sig;
+ int error;
+
+ error = sigwait(&set, &sig);
+ if (error)
+ {
+ DBG1(DBG_DMN, "error %d while waiting for a signal", error);
+ return;
+ }
+ switch (sig)
+ {
+ case SIGINT:
+ {
+ DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ case SIGTERM:
+ {
+ DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
+ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
+ return;
+ }
+ default:
+ {
+ DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig);
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Handle SIGSEGV/SIGILL signals raised by threads
+ */
+static void segv_handler(int signal)
+{
+ backtrace_t *backtrace;
+
+ DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr, TRUE);
+ backtrace->destroy(backtrace);
+
+ DBG1(DBG_DMN, "killing ourself, received critical signal");
+ abort();
+}
+
+/**
+ * Lookup UID and GID
+ */
+static bool lookup_uid_gid()
+{
+#ifdef IPSEC_USER
+ if (!charon->caps->resolve_uid(charon->caps, IPSEC_USER))
+ {
+ return FALSE;
+ }
+#endif
+#ifdef IPSEC_GROUP
+ if (!charon->caps->resolve_gid(charon->caps, IPSEC_GROUP))
+ {
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+
+/**
+ * Check/create PID file, return TRUE if already running
+ */
+static bool check_pidfile()
+{
+ struct stat stb;
+
+ if (stat(pidfile_name, &stb) == 0)
+ {
+ pidfile = fopen(pidfile_name, "r");
+ if (pidfile)
+ {
+ char buf[64];
+ pid_t pid = 0;
+
+ memset(buf, 0, sizeof(buf));
+ if (fread(buf, 1, sizeof(buf), pidfile))
+ {
+ buf[sizeof(buf) - 1] = '\0';
+ pid = atoi(buf);
+ }
+ fclose(pidfile);
+ if (pid && kill(pid, 0) == 0)
+ { /* such a process is running */
+ return TRUE;
+ }
+ }
+ DBG1(DBG_DMN, "removing pidfile '%s', process not running", pidfile_name);
+ unlink(pidfile_name);
+ }
+
+ /* create new pidfile */
+ pidfile = fopen(pidfile_name, "w");
+ if (pidfile)
+ {
+ ignore_result(fchown(fileno(pidfile),
+ charon->caps->get_uid(charon->caps),
+ charon->caps->get_gid(charon->caps)));
+ fprintf(pidfile, "%d\n", getpid());
+ fflush(pidfile);
+ }
+ return FALSE;
+}
+
+/**
+ * Delete/truncate the PID file
+ */
+static void unlink_pidfile()
+{
+ /* because unlinking the PID file may fail, we truncate it to ensure the
+ * daemon can be properly restarted. one probable cause for this is the
+ * combination of not running as root and the effective user lacking
+ * permissions on the parent dir(s) of the PID file */
+ if (pidfile)
+ {
+ ignore_result(ftruncate(fileno(pidfile), 0));
+ fclose(pidfile);
+ }
+ unlink(pidfile_name);
+}
+/**
+ * Main function, starts TKM backend.
+ */
+int main(int argc, char *argv[])
+{
+ char *dmn_name;
+ if (argc > 0 && strlen(argv[0]) > 0)
+ {
+ dmn_name = basename(argv[0]);
+ }
+ else
+ {
+ dmn_name = "charon-tkm";
+ }
+
+ struct sigaction action;
+ int status = SS_RC_INITIALIZATION_FAILED;
+
+ /* logging for library during initialization, as we have no bus yet */
+ dbg = dbg_syslog;
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ library_deinit();
+ exit(status);
+ }
+
+ if (!libhydra_init(dmn_name))
+ {
+ dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name);
+ libhydra_deinit();
+ library_deinit();
+ exit(status);
+ }
+
+ if (!libcharon_init(dmn_name))
+ {
+ dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name);
+ goto deinit;
+ }
+
+ if (!lookup_uid_gid())
+ {
+ dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting %s", dmn_name);
+ goto deinit;
+ }
+
+ /* make sure we log to the DAEMON facility by default */
+ lib->settings->set_int(lib->settings, "%s.syslog.daemon.default",
+ lib->settings->get_int(lib->settings, "%s.syslog.daemon.default", 1,
+ dmn_name), dmn_name);
+ charon->load_loggers(charon, NULL, FALSE);
+
+ DBG1(DBG_DMN, "Starting charon with TKM backend (strongSwan "VERSION")");
+
+ /* initialize daemon */
+ if (!charon->initialize(charon, PLUGINS))
+ {
+ DBG1(DBG_DMN, "initialization failed - aborting %s", dmn_name);
+ goto deinit;
+ }
+
+ /* set global pidfile name depending on daemon name */
+ if (asprintf(&pidfile_name, IPSEC_PIDDIR"/%s.pid", dmn_name) < 0)
+ {
+ DBG1(DBG_DMN, "unable to set pidfile name - aborting %s", dmn_name);
+ goto deinit;
+ };
+
+ if (check_pidfile())
+ {
+ DBG1(DBG_DMN, "%s already running (\"%s\" exists)", dmn_name,
+ pidfile_name);
+ goto deinit;
+ }
+
+ if (!charon->caps->drop(charon->caps))
+ {
+ DBG1(DBG_DMN, "capability dropping failed - aborting %s", dmn_name);
+ goto deinit;
+ }
+
+ /* initialize TKM client lib */
+ tkmlib_init();
+
+ /* add handler for SEGV and ILL,
+ * INT and TERM are handled by sigwait() in run() */
+ action.sa_handler = segv_handler;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGINT);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaction(SIGSEGV, &action, NULL);
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
+
+ /* start daemon (i.e. the threads in the thread-pool) */
+ charon->start(charon);
+
+ /* main thread goes to run loop */
+ run();
+
+ unlink_pidfile();
+ status = 0;
+ tkmlib_final();
+
+deinit:
+ libcharon_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return status;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 "tkm.h"
+
+typedef struct private_tkm_t private_tkm_t;
+
+/**
+ * Private additions to tkm_t.
+ */
+struct private_tkm_t {
+
+ /**
+ * Public members of tkm_t.
+ */
+ tkm_t public;
+};
+
+/**
+ * Single instance of tkm_t.
+ */
+tkm_t *tkm = NULL;
+
+/**
+ * Described in header.
+ */
+bool tkm_init()
+{
+ private_tkm_t *this;
+
+ INIT(this,
+ .public = {
+ .idmgr = tkm_id_manager_create(),
+ },
+ );
+ tkm = &this->public;
+
+ return TRUE;
+}
+
+/**
+ * Described in header.
+ */
+void tkm_deinit()
+{
+ if (!tkm)
+ {
+ return;
+ }
+ private_tkm_t *this = (private_tkm_t*)tkm;
+ this->public.idmgr->destroy(this->public.idmgr);
+ free(this);
+ tkm = NULL;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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.
+ */
+
+#ifndef TKM_H_
+#define TKM_H_
+
+#include "tkm_id_manager.h"
+
+typedef struct tkm_t tkm_t;
+
+/**
+ * Trusted key manager context, contains tkm related globals.
+ */
+struct tkm_t {
+
+ /**
+ * Context ID manager.
+ */
+ tkm_id_manager_t *idmgr;
+
+};
+
+/**
+ * Initialize trusted key manager, creates "tkm" instance.
+ *
+ * @return FALSE if initialization error occured
+ */
+bool tkm_init();
+
+/**
+ * Deinitialize trusted key manager, destroys "tkm" instance.
+ */
+void tkm_deinit();
+
+/**
+ * Trusted key manager instance, set after tkm_init() and before tkm_deinit()
+ * calls.
+ */
+extern tkm_t *tkm;
+
+#endif /** TKM_H_ */
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 "tkm_id_manager.h"
+
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <threading/rwlock.h>
+
+ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_NONCE,
+ "NONCE_CONTEXT");
+ENUM_END(tkm_context_kind_names, TKM_CTX_NONCE);
+
+typedef struct private_tkm_id_manager_t private_tkm_id_manager_t;
+
+/**
+ * private data of tkm_id_manager
+ */
+struct private_tkm_id_manager_t {
+
+ /**
+ * public functions
+ */
+ tkm_id_manager_t public;
+
+ /**
+ * Next free context id values.
+ */
+ int nextids[TKM_CTX_MAX];
+
+ /**
+ * Per-kind list of acquired context ids
+ */
+ linked_list_t *ctxids[TKM_CTX_MAX];
+
+ /**
+ * rwlocks for context id lists
+ */
+ rwlock_t *locks[TKM_CTX_MAX];
+
+};
+
+/**
+ * Check if given kind is a valid context kind value.
+ *
+ * @param kind context kind to check
+ * @return TRUE if given kind is a valid context kind,
+ * FALSE otherwise
+ */
+static bool is_valid_kind(const tkm_context_kind_t kind)
+{
+ return (int)kind >= 0 && kind < TKM_CTX_MAX;
+};
+
+METHOD(tkm_id_manager_t, acquire_id, int,
+ private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
+{
+ int *current;
+ int id = 0;
+
+ if (!is_valid_kind(kind))
+ {
+ DBG1(DBG_LIB, "tried to acquire id for invalid context kind '%d'",
+ kind);
+ return 0;
+ }
+
+ this->locks[kind]->write_lock(this->locks[kind]);
+
+ id = this->nextids[kind];
+ current = malloc(sizeof(int));
+ *current = id;
+ this->ctxids[kind]->insert_last(this->ctxids[kind], current);
+ this->nextids[kind]++;
+
+ this->locks[kind]->unlock(this->locks[kind]);
+
+ if (!id)
+ {
+ DBG1(DBG_LIB, "acquiring %N context id failed",
+ tkm_context_kind_names, kind);
+ }
+
+ return id;
+}
+
+METHOD(tkm_id_manager_t, release_id, bool,
+ private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
+ const int id)
+{
+ enumerator_t *enumerator;
+ int *current;
+ bool found = FALSE;
+
+ if (!is_valid_kind(kind))
+ {
+ DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'",
+ id, kind);
+ return FALSE;
+ }
+
+ this->locks[kind]->write_lock(this->locks[kind]);
+ enumerator = this->ctxids[kind]->create_enumerator(this->ctxids[kind]);
+ while (enumerator->enumerate(enumerator, ¤t))
+ {
+ if (*current == id)
+ {
+ this->ctxids[kind]->remove_at(this->ctxids[kind], enumerator);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->locks[kind]->unlock(this->locks[kind]);
+
+ if (!found)
+ {
+ DBG3(DBG_LIB, "releasing non-existent %N context id %d, nothing to do",
+ tkm_context_kind_names, kind, id);
+ }
+
+ return TRUE;
+}
+
+
+METHOD(tkm_id_manager_t, destroy, void,
+ private_tkm_id_manager_t *this)
+{
+ int i;
+
+ for (i = 0; i < TKM_CTX_MAX; i++)
+ {
+ this->ctxids[i]->destroy(this->ctxids[i]);
+ this->locks[i]->destroy(this->locks[i]);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+tkm_id_manager_t *tkm_id_manager_create()
+{
+ private_tkm_id_manager_t *this;
+ int i;
+
+ INIT(this,
+ .public = {
+ .acquire_id = _acquire_id,
+ .release_id = _release_id,
+ .destroy = _destroy,
+ },
+ );
+
+ for (i = 0; i < TKM_CTX_MAX; i++)
+ {
+ this->nextids[i] = 1;
+ this->ctxids[i] = linked_list_create();
+ this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ }
+
+ return &this->public;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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.
+ */
+
+#ifndef TKM_ID_MANAGER_H_
+#define TKM_ID_MANAGER_H_
+
+#include <library.h>
+
+typedef struct tkm_id_manager_t tkm_id_manager_t;
+typedef enum tkm_context_kind_t tkm_context_kind_t;
+
+/**
+ * Trusted key manager context kinds.
+ */
+enum tkm_context_kind_t {
+ /** Nonce context */
+ TKM_CTX_NONCE,
+
+ /** helper to determine the number of elements in this enum */
+ TKM_CTX_MAX,
+};
+
+/**
+ * enum name for context_kind_t.
+ */
+extern enum_name_t *tkm_context_kind_names;
+
+/**
+ * The tkm id manager hands out context ids for all context kinds (e.g. nonce).
+ */
+struct tkm_id_manager_t {
+
+ /**
+ * Acquire new context id for a specific context kind.
+ *
+ * @param kind kind of context id to acquire
+ * @return context id of given kind,
+ * 0 if no id of given kind could be acquired
+ */
+ int (*acquire_id)(tkm_id_manager_t * const this,
+ const tkm_context_kind_t kind);
+
+ /**
+ * Release a previously acquired context id.
+ *
+ * @param kind kind of context id to release
+ * @param id id to release
+ * @return TRUE if id was released, FALSE otherwise
+ */
+ bool (*release_id)(tkm_id_manager_t * const this,
+ const tkm_context_kind_t kind,
+ const int id);
+
+ /**
+ * Destroy a tkm_id_manager instance.
+ */
+ void (*destroy)(tkm_id_manager_t *this);
+
+};
+
+/**
+ * Create a tkm id manager instance.
+ */
+tkm_id_manager_t *tkm_id_manager_create();
+
+#endif /** TKM_ID_MANAGER_H_ */
--- /dev/null
+/*
+ * Copyrigth (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 "tkm_nonceg.h"
+
+typedef struct private_tkm_nonceg_t private_tkm_nonceg_t;
+
+/**
+ * Private data of a tkm_nonceg_t object.
+ */
+struct private_tkm_nonceg_t {
+
+ /**
+ * Public tkm_nonceg_t interface.
+ */
+ tkm_nonceg_t public;
+
+};
+
+METHOD(nonce_gen_t, get_nonce, bool,
+ private_tkm_nonceg_t *this, size_t size, u_int8_t *buffer)
+{
+ // TODO: Request nonce from TKM and fill it into buffer.
+ return TRUE;
+}
+
+METHOD(nonce_gen_t, allocate_nonce, bool,
+ private_tkm_nonceg_t *this, size_t size, chunk_t *chunk)
+{
+ *chunk = chunk_alloc(size);
+ return get_nonce(this, chunk->len, chunk->ptr);
+}
+
+METHOD(nonce_gen_t, destroy, void,
+ private_tkm_nonceg_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+tkm_nonceg_t *tkm_nonceg_create()
+{
+ private_tkm_nonceg_t *this;
+
+ INIT(this,
+ .public = {
+ .nonce_gen = {
+ .get_nonce = _get_nonce,
+ .allocate_nonce = _allocate_nonce,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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.
+ */
+
+#ifndef TKM_NONCEG_H_
+#define TKM_NONCEG_H_
+
+typedef struct tkm_nonceg_t tkm_nonceg_t;
+
+#include <library.h>
+
+/**
+ * nonce_gen_t implementation using the trusted key manager.
+ */
+struct tkm_nonceg_t {
+
+ /**
+ * Implements nonce_gen_t.
+ */
+ nonce_gen_t nonce_gen;
+};
+
+/**
+ * Creates a tkm_nonceg_t instance.
+ *
+ * @return created tkm_nonceg_t
+ */
+tkm_nonceg_t *tkm_nonceg_create();
+
+#endif /** TKM_NONCEG_H_ */
--- /dev/null
+test_runner
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 <stdlib.h>
+#include <check.h>
+
+#include "tkm_id_manager.h"
+
+START_TEST(test_id_mgr_creation)
+{
+ tkm_id_manager_t *idmgr = NULL;
+
+ idmgr = tkm_id_manager_create();
+ fail_if(idmgr == NULL, "Error creating tkm id manager");
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_acquire_id)
+{
+ int i, id = 0;
+ tkm_id_manager_t *idmgr = tkm_id_manager_create();
+
+ for (i = 0; i < TKM_CTX_MAX; i++)
+ {
+ id = idmgr->acquire_id(idmgr, i);
+ fail_unless(id > 0, "Error acquiring id of context kind %d", i);
+
+ /* Reset test variable */
+ id = 0;
+ }
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_acquire_id_invalid_kind)
+{
+ int id = 0;
+ tkm_id_manager_t *idmgr = tkm_id_manager_create();
+
+ id = idmgr->acquire_id(idmgr, TKM_CTX_MAX);
+ fail_unless(id == 0, "Acquired id for invalid context kind %d", TKM_CTX_MAX);
+
+ /* Reset test variable */
+ id = 0;
+
+ id = idmgr->acquire_id(idmgr, -1);
+ fail_unless(id == 0, "Acquired id for invalid context kind %d", -1);
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_release_id)
+{
+ int i, id = 0;
+ bool released = false;
+ tkm_id_manager_t *idmgr = tkm_id_manager_create();
+
+ for (i = 0; i < TKM_CTX_MAX; i++)
+ {
+ id = idmgr->acquire_id(idmgr, i);
+ released = idmgr->release_id(idmgr, i, id);
+
+ fail_unless(released, "Error releasing id of context kind %d", i);
+
+ /* Reset released variable */
+ released = FALSE;
+ }
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_release_id_invalid_kind)
+{
+ bool released = TRUE;
+ tkm_id_manager_t *idmgr = tkm_id_manager_create();
+
+ released = idmgr->release_id(idmgr, TKM_CTX_MAX, 1);
+ fail_if(released, "Released id for invalid context kind %d", TKM_CTX_MAX);
+
+ /* Reset test variable */
+ released = TRUE;
+
+ released = idmgr->release_id(idmgr, -1, 1);
+ fail_if(released, "Released id for invalid context kind %d", -1);
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_release_id_nonexistent)
+{
+ bool released = FALSE;
+ tkm_id_manager_t *idmgr = tkm_id_manager_create();
+
+ released = idmgr->release_id(idmgr, TKM_CTX_NONCE, 1);
+ fail_unless(released, "Release of nonexistent id failed");
+
+ idmgr->destroy(idmgr);
+}
+END_TEST
+
+TCase *make_id_manager_tests(void)
+{
+ TCase *tc = tcase_create("Context id manager tests");
+ tcase_add_test(tc, test_id_mgr_creation);
+ tcase_add_test(tc, test_acquire_id);
+ tcase_add_test(tc, test_acquire_id_invalid_kind);
+ tcase_add_test(tc, test_release_id);
+ tcase_add_test(tc, test_release_id_invalid_kind);
+ tcase_add_test(tc, test_release_id_nonexistent);
+
+ return tc;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 <check.h>
+#include <tkm/client.h>
+
+#include "tkm.h"
+#include "tkm_nonceg.h"
+
+START_TEST(test_nonceg_creation)
+{
+ tkm_nonceg_t *ng = NULL;
+
+ ng = tkm_nonceg_create();
+ fail_if(ng == NULL, "Error creating tkm nonce generator");
+
+ ng->nonce_gen.destroy(&ng->nonce_gen);
+}
+END_TEST
+
+START_TEST(test_nonceg_allocate_nonce)
+{
+ tkm_nonceg_t *ng = tkm_nonceg_create();
+
+ const size_t length = 256;
+ u_int8_t zero[length];
+ memset(zero, 0, length);
+
+ chunk_t nonce;
+ const bool got_nonce = ng->nonce_gen.allocate_nonce(&ng->nonce_gen,
+ length, &nonce);
+
+ fail_unless(got_nonce, "Call to allocate_nonce failed");
+ fail_unless(nonce.len = length, "Allocated nonce length mismatch");
+ fail_if(memcmp(nonce.ptr, zero, length) == 0, "Unable to allocate nonce");
+
+ tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, 1);
+ ike_nc_reset(1);
+
+ chunk_free(&nonce);
+ ng->nonce_gen.destroy(&ng->nonce_gen);
+}
+END_TEST
+
+START_TEST(test_nonceg_get_nonce)
+{
+ tkm_nonceg_t *ng = tkm_nonceg_create();
+
+ const size_t length = 128;
+ u_int8_t zero[length];
+ memset(zero, 0, length);
+
+ u_int8_t *buf = malloc(length + 1);
+ memset(buf, 0, length);
+ /* set end marker */
+ buf[length] = 255;
+
+ const bool got_nonce = ng->nonce_gen.get_nonce(&ng->nonce_gen, length, buf);
+ fail_unless(got_nonce, "Call to get_nonce failed");
+ fail_if(memcmp(buf, zero, length) == 0, "Unable to get nonce");
+ fail_if(buf[length] != 255, "End marker not found");
+
+ tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, 1);
+ ike_nc_reset(1);
+
+ free(buf);
+ ng->nonce_gen.destroy(&ng->nonce_gen);
+}
+END_TEST
+
+TCase *make_nonceg_tests(void)
+{
+ TCase *tc = tcase_create("Nonce generator tests");
+ tcase_add_test(tc, test_nonceg_creation);
+ tcase_add_test(tc, test_nonceg_allocate_nonce);
+ tcase_add_test(tc, test_nonceg_get_nonce);
+
+ return tc;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 <stdlib.h>
+
+#include "test_runner.h"
+
+int main(void)
+{
+ int number_failed;
+ Suite *s = suite_create("TKM tests");
+ suite_add_tcase(s, make_id_manager_tests());
+ suite_add_tcase(s, make_nonceg_tests());
+
+ SRunner *sr = srunner_create(s);
+
+ srunner_run_all(sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed(sr);
+
+ srunner_free(sr);
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Reto Buerki
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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.
+ */
+
+#ifndef TEST_RUNNER_H_
+#define TEST_RUNNER_H_
+
+#include <check.h>
+
+TCase *make_id_manager_tests(void);
+TCase *make_nonceg_tests(void);
+
+#endif /** TEST_RUNNER_H_ */