diff options
author | Reto Buerki <reet@codelabs.ch> | 2012-05-18 14:09:24 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-03-19 15:23:45 +0100 |
commit | 559fe48c5040788c5d8135f00905afb16e5ccaf7 (patch) | |
tree | dce9886c360bd9f342b72386a7d94a834f603032 /src | |
parent | 4dc3ef94a1b697c64bfc714bb129a5a5d0e1873c (diff) | |
download | strongswan-559fe48c5040788c5d8135f00905afb16e5ccaf7.tar.bz2 strongswan-559fe48c5040788c5d8135f00905afb16e5ccaf7.tar.xz |
Introduce TKM specific charon daemon (charon-tkm)
Analogous to charon-nm the charon-tkm daemon is a specialized charon
instance used in combination with the trusted key manager (TKM) written
in Ada.
The charon-tkm is basically a copy of the charon-nm code which will
register it's own TKM specific plugins.
The daemon binary is built using the gprbuild utility. This is needed
because it uses the tkm-rpc Ada library and consequently the Ada
runtime. gprbuild takes care of the complete binding and linker steps
required to properly initialize the Ada runtime.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/charon-tkm/.gitignore | 1 | ||||
-rw-r--r-- | src/charon-tkm/Makefile.am | 63 | ||||
-rw-r--r-- | src/charon-tkm/build_charon.gpr | 15 | ||||
-rw-r--r-- | src/charon-tkm/build_common.gpr | 10 | ||||
-rw-r--r-- | src/charon-tkm/build_tests.gpr | 14 | ||||
-rw-r--r-- | src/charon-tkm/src/charon-tkm.c | 330 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/.gitignore | 1 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm.c | 67 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm.h | 54 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_id_manager.c | 176 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_id_manager.h | 79 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_nonceg.c | 71 | ||||
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_nonceg.h | 42 | ||||
-rw-r--r-- | src/charon-tkm/tests/.gitignore | 1 | ||||
-rw-r--r-- | src/charon-tkm/tests/id_manager_tests.c | 131 | ||||
-rw-r--r-- | src/charon-tkm/tests/nonceg_tests.c | 92 | ||||
-rw-r--r-- | src/charon-tkm/tests/test_runner.c | 36 | ||||
-rw-r--r-- | src/charon-tkm/tests/test_runner.h | 25 |
19 files changed, 1212 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e71f73db3..07953b0b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,6 +100,10 @@ if USE_INTEGRITY_TEST SUBDIRS += checksum endif +if USE_TKM + SUBDIRS += charon-tkm +endif + EXTRA_DIST = strongswan.conf install-exec-local : diff --git a/src/charon-tkm/.gitignore b/src/charon-tkm/.gitignore new file mode 100644 index 000000000..b672fdeaf --- /dev/null +++ b/src/charon-tkm/.gitignore @@ -0,0 +1 @@ +obj diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am new file mode 100644 index 000000000..44586dc4a --- /dev/null +++ b/src/charon-tkm/Makefile.am @@ -0,0 +1,63 @@ +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 diff --git a/src/charon-tkm/build_charon.gpr b/src/charon-tkm/build_charon.gpr new file mode 100644 index 000000000..c162376a8 --- /dev/null +++ b/src/charon-tkm/build_charon.gpr @@ -0,0 +1,15 @@ +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; diff --git a/src/charon-tkm/build_common.gpr b/src/charon-tkm/build_common.gpr new file mode 100644 index 000000000..d742692ef --- /dev/null +++ b/src/charon-tkm/build_common.gpr @@ -0,0 +1,10 @@ +with "tkmrpc_client"; + +project Build_Common is + + for Source_Dirs use (); + + Obj_Dir := "obj"; + Compiler_Switches := ("-W", "-Wall", "-Wno-unused-parameter"); + +end Build_Common; diff --git a/src/charon-tkm/build_tests.gpr b/src/charon-tkm/build_tests.gpr new file mode 100644 index 000000000..35f0c9bdd --- /dev/null +++ b/src/charon-tkm/build_tests.gpr @@ -0,0 +1,14 @@ +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; diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c new file mode 100644 index 000000000..8731d7831 --- /dev/null +++ b/src/charon-tkm/src/charon-tkm.c @@ -0,0 +1,330 @@ +/* + * 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; +} diff --git a/src/charon-tkm/src/tkm/.gitignore b/src/charon-tkm/src/tkm/.gitignore new file mode 100644 index 000000000..b672fdeaf --- /dev/null +++ b/src/charon-tkm/src/tkm/.gitignore @@ -0,0 +1 @@ +obj diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c new file mode 100644 index 000000000..1e61f882b --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm.c @@ -0,0 +1,67 @@ +/* + * 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; +} diff --git a/src/charon-tkm/src/tkm/tkm.h b/src/charon-tkm/src/tkm/tkm.h new file mode 100644 index 000000000..6bb8331d4 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm.h @@ -0,0 +1,54 @@ +/* + * 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_ */ diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c new file mode 100644 index 000000000..4a1afe37f --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -0,0 +1,176 @@ +/* + * 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; +} diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h new file mode 100644 index 000000000..f348b6d57 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -0,0 +1,79 @@ +/* + * 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_ */ diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c new file mode 100644 index 000000000..1a83a5b16 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -0,0 +1,71 @@ +/* + * 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; +} diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.h b/src/charon-tkm/src/tkm/tkm_nonceg.h new file mode 100644 index 000000000..907890bbd --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_nonceg.h @@ -0,0 +1,42 @@ +/* + * 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_ */ diff --git a/src/charon-tkm/tests/.gitignore b/src/charon-tkm/tests/.gitignore new file mode 100644 index 000000000..35429f617 --- /dev/null +++ b/src/charon-tkm/tests/.gitignore @@ -0,0 +1 @@ +test_runner diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c new file mode 100644 index 000000000..0942c299a --- /dev/null +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -0,0 +1,131 @@ +/* + * 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; +} diff --git a/src/charon-tkm/tests/nonceg_tests.c b/src/charon-tkm/tests/nonceg_tests.c new file mode 100644 index 000000000..202a9e5c7 --- /dev/null +++ b/src/charon-tkm/tests/nonceg_tests.c @@ -0,0 +1,92 @@ +/* + * 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; +} diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c new file mode 100644 index 000000000..61c252416 --- /dev/null +++ b/src/charon-tkm/tests/test_runner.c @@ -0,0 +1,36 @@ +/* + * 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; +} diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h new file mode 100644 index 000000000..3d15fb99f --- /dev/null +++ b/src/charon-tkm/tests/test_runner.h @@ -0,0 +1,25 @@ +/* + * 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_ */ |