From 4dc3ef94a1b697c64bfc714bb129a5a5d0e1873c Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 22 Jan 2013 16:13:15 +0100 Subject: starter: Make daemon name configurable A daemon can be specified using the '--daemon' command line parameter. This tells starter to invoke a daemon other than 'charon'. Additionally the ipsec script uses the environment variable DAEMON_NAME to tell the starter which daemon to use. --- src/ipsec/_ipsec.in | 9 ++-- src/starter/confread.c | 2 +- src/starter/files.h | 8 ++-- src/starter/invokecharon.c | 37 +++++++++------- src/starter/starter.c | 108 +++++++++++++++++++++++++++++++++++++++------ 5 files changed, 126 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in index 6b406f6d9..3742b12c7 100644 --- a/src/ipsec/_ipsec.in +++ b/src/ipsec/_ipsec.in @@ -18,6 +18,9 @@ PATH="/sbin:/bin:/usr/sbin:/usr/bin:@IPSEC_SBINDIR@" export PATH +# set daemon name +[ -z "$DAEMON_NAME" ] && DAEMON_NAME="charon" + # name and version of the ipsec implementation OS_NAME=`uname -s` IPSEC_NAME="@IPSEC_NAME@" @@ -30,8 +33,8 @@ IPSEC_CONFDIR="@IPSEC_CONFDIR@" IPSEC_PIDDIR="@IPSEC_PIDDIR@" IPSEC_SCRIPT="@IPSEC_SCRIPT@" -IPSEC_STARTER_PID="${IPSEC_PIDDIR}/starter.pid" -IPSEC_CHARON_PID="${IPSEC_PIDDIR}/charon.pid" +IPSEC_STARTER_PID="${IPSEC_PIDDIR}/starter.${DAEMON_NAME}.pid" +IPSEC_CHARON_PID="${IPSEC_PIDDIR}/${DAEMON_NAME}.pid" IPSEC_STROKE="${IPSEC_DIR}/stroke" IPSEC_STARTER="${IPSEC_DIR}/starter" @@ -220,7 +223,7 @@ start) if [ -d /var/lock/subsys ]; then touch /var/lock/subsys/ipsec fi - exec $IPSEC_STARTER "$@" + exec $IPSEC_STARTER --daemon $DAEMON_NAME "$@" ;; status|statusall) op="$1" diff --git a/src/starter/confread.c b/src/starter/confread.c index 883534aad..f0f05b036 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -190,7 +190,7 @@ static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp) /* verify the executables are actually available */ #ifdef START_CHARON cfg->setup.charonstart = cfg->setup.charonstart && - daemon_exists("charon", CHARON_CMD); + daemon_exists(daemon_name, cmd); #else cfg->setup.charonstart = FALSE; #endif diff --git a/src/starter/files.h b/src/starter/files.h index 96b76fdf1..76cdaa986 100644 --- a/src/starter/files.h +++ b/src/starter/files.h @@ -15,8 +15,6 @@ #ifndef _STARTER_FILES_H_ #define _STARTER_FILES_H_ -#define STARTER_PID_FILE IPSEC_PIDDIR "/starter.pid" - #define PROC_NETKEY "/proc/net/pfkey" #define PROC_KLIPS "/proc/net/pf_key" #define PROC_MODULES "/proc/modules" @@ -24,9 +22,11 @@ #define CONFIG_FILE IPSEC_CONFDIR "/ipsec.conf" #define SECRETS_FILE IPSEC_CONFDIR "/ipsec.secrets" -#define CHARON_CMD IPSEC_DIR "/charon" #define CHARON_CTL_FILE IPSEC_PIDDIR "/charon.ctl" -#define CHARON_PID_FILE IPSEC_PIDDIR "/charon.pid" + +extern char *daemon_name; +extern char *cmd; +extern char *pid_file; #define DYNIP_DIR IPSEC_PIDDIR "/dynip" diff --git a/src/starter/invokecharon.c b/src/starter/invokecharon.c index 1c93381f7..d981f6c17 100644 --- a/src/starter/invokecharon.c +++ b/src/starter/invokecharon.c @@ -46,22 +46,22 @@ void starter_charon_sigchild(pid_t pid, int status) if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY || status == SS_RC_DAEMON_INTEGRITY) { - DBG1(DBG_APP, "charon has quit: integrity test of %s failed", - (status == 64) ? "libstrongswan" : "charon"); + DBG1(DBG_APP, "%s has quit: integrity test of %s failed", + daemon_name, (status == 64) ? "libstrongswan" : daemon_name); _stop_requested = 1; } else if (status == SS_RC_INITIALIZATION_FAILED) { - DBG1(DBG_APP, "charon has quit: initialization failed"); + DBG1(DBG_APP, "%s has quit: initialization failed", daemon_name); _stop_requested = 1; } if (!_stop_requested) { - DBG1(DBG_APP, "charon has died -- restart scheduled (%dsec)", - CHARON_RESTART_DELAY); + DBG1(DBG_APP, "%s has died -- restart scheduled (%dsec)", + daemon_name, CHARON_RESTART_DELAY); alarm(CHARON_RESTART_DELAY); // restart in 5 sec } - unlink(CHARON_PID_FILE); + unlink(pid_file); } } @@ -88,7 +88,8 @@ int starter_stop_charon (void) else if (i == 40) { kill(pid, SIGKILL); - DBG1(DBG_APP, "starter_stop_charon(): charon does not respond, sending KILL"); + DBG1(DBG_APP, "starter_stop_charon(): %s does not respond, sending KILL", + daemon_name); } else { @@ -98,15 +99,15 @@ int starter_stop_charon (void) } if (_charon_pid == 0) { - DBG1(DBG_APP, "charon stopped after %d ms", 200*i); + DBG1(DBG_APP, "%s stopped after %d ms", daemon_name, 200*i); return 0; } - DBG1(DBG_APP, "starter_stop_charon(): can't stop charon !!!"); + DBG1(DBG_APP, "starter_stop_charon(): can't stop %s !!!", daemon_name); return -1; } else { - DBG1(DBG_APP, "stater_stop_charon(): charon was not started..."); + DBG1(DBG_APP, "stater_stop_charon(): %s was not started...", daemon_name); } return -1; } @@ -119,7 +120,7 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) char buffer[BUF_LEN]; int argc = 1; char *arg[] = { - CHARON_CMD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + cmd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL @@ -130,7 +131,7 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) argc = 0; arg[argc++] = "/usr/bin/gdb"; arg[argc++] = "--args"; - arg[argc++] = CHARON_CMD; + arg[argc++] = cmd; } if (!no_fork) { @@ -172,7 +173,8 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) if (_charon_pid) { - DBG1(DBG_APP, "starter_start_charon(): charon already started..."); + DBG1(DBG_APP, "starter_start_charon(): %s already started...", + daemon_name); return -1; } else @@ -203,9 +205,9 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) { /* wait for charon for a maximum of 500 x 20 ms = 10 s */ usleep(20000); - if (stat(CHARON_PID_FILE, &stb) == 0) + if (stat(pid_file, &stb) == 0) { - DBG1(DBG_APP, "charon (%d) started after %d ms", + DBG1(DBG_APP, "%s (%d) started after %d ms", daemon_name, _charon_pid, 20*(i+1)); return 0; } @@ -213,7 +215,8 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) if (_charon_pid) { /* If charon is started but with no ctl file, stop it */ - DBG1(DBG_APP, "charon too long to start... - kill kill"); + DBG1(DBG_APP, "%s too long to start... - kill kill", + daemon_name); for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++) { if (i == 0) @@ -233,7 +236,7 @@ int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb) } else { - DBG1(DBG_APP, "charon refused to be started"); + DBG1(DBG_APP, "%s refused to be started", daemon_name); } return -1; } diff --git a/src/starter/starter.c b/src/starter/starter.c index ae6863fd7..917e52d68 100644 --- a/src/starter/starter.c +++ b/src/starter/starter.c @@ -12,6 +12,8 @@ * for more details. */ +#define _GNU_SOURCE + #include #include #include @@ -50,6 +52,15 @@ #define CHARON_RESTART_DELAY 5 +static const char* cmd_default = IPSEC_DIR "/charon"; +static const char* pid_file_default = IPSEC_PIDDIR "/charon.pid"; +static const char* starter_pid_file_default = IPSEC_PIDDIR "/starter.pid"; + +char *daemon_name = NULL; +char *cmd = NULL; +char *pid_file = NULL; +char *starter_pid_file = NULL; + /* logging */ static bool log_to_stderr = TRUE; static bool log_to_syslog = TRUE; @@ -162,7 +173,10 @@ static void signal_handler(int signal) { if (pid == starter_charon_pid()) { - name = " (Charon)"; + if (asprintf(&name, " (%s)", daemon_name) < 0) + { + name = NULL; + } } if (WIFSIGNALED(status)) { @@ -193,6 +207,11 @@ static void signal_handler(int signal) starter_charon_sigchild(pid, exit_status); } } + + if (name) + { + free(name); + } } break; @@ -325,11 +344,56 @@ static bool check_pid(char *pid_file) return FALSE; } +/* Set daemon name and adjust command and pid filenames accordingly */ +static bool set_daemon_name() +{ + if (!daemon_name) + { + daemon_name = "charon"; + } + + if (asprintf(&cmd, IPSEC_DIR"/%s", daemon_name) < 0) + { + cmd = (char*)cmd_default; + } + + if (asprintf(&pid_file, IPSEC_PIDDIR"/%s.pid", daemon_name) < 0) + { + pid_file = (char*)pid_file_default; + } + + if (asprintf(&starter_pid_file, IPSEC_PIDDIR"/starter.%s.pid", + daemon_name) < 0) + { + starter_pid_file = (char*)starter_pid_file_default; + } + + return TRUE; +} + +static void cleanup() +{ + if (cmd != cmd_default) + { + free(cmd); + } + + if (pid_file != pid_file_default) + { + free(pid_file); + } + + if (starter_pid_file != starter_pid_file_default) + { + free(starter_pid_file); + } +} + static void usage(char *name) { fprintf(stderr, "Usage: starter [--nofork] [--auto-update ]\n" " [--debug|--debug-more|--debug-all|--nolog]\n" - " [--attach-gdb]\n"); + " [--attach-gdb] [--daemon ]\n"); exit(LSB_RC_INVALID_ARGUMENT); } @@ -392,12 +456,22 @@ int main (int argc, char **argv) if (!auto_update) usage(argv[0]); } + else if (streq(argv[i], "--daemon") && i+1 < argc) + { + daemon_name = argv[++i]; + } else { usage(argv[0]); } } + if (!set_daemon_name()) + { + DBG1(DBG_APP, "unable to set daemon name"); + exit(LSB_RC_FAILURE); + } + init_log("ipsec_starter"); DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...", @@ -423,13 +497,14 @@ int main (int argc, char **argv) if (getuid() != 0) { DBG1(DBG_APP, "permission denied (must be superuser)"); + cleanup(); exit(LSB_RC_NOT_ALLOWED); } - if (check_pid(CHARON_PID_FILE)) + if (check_pid(pid_file)) { - DBG1(DBG_APP, "charon is already running (%s exists) -- skipping charon start", - CHARON_PID_FILE); + DBG1(DBG_APP, "%s is already running (%s exists) -- skipping daemon start", + daemon_name, pid_file); } else { @@ -438,12 +513,14 @@ int main (int argc, char **argv) if (stat(DEV_RANDOM, &stb) != 0) { DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_RANDOM); + cleanup(); exit(LSB_RC_FAILURE); } if (stat(DEV_URANDOM, &stb)!= 0) { DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_URANDOM); + cleanup(); exit(LSB_RC_FAILURE); } @@ -455,6 +532,7 @@ int main (int argc, char **argv) { confread_free(cfg); } + cleanup(); exit(LSB_RC_INVALID_ARGUMENT); } @@ -471,11 +549,12 @@ int main (int argc, char **argv) last_reload = time_monotonic(NULL); - if (check_pid(STARTER_PID_FILE)) + if (check_pid(starter_pid_file)) { DBG1(DBG_APP, "starter is already running (%s exists) -- no fork done", - STARTER_PID_FILE); + starter_pid_file); confread_free(cfg); + cleanup(); exit(LSB_RC_SUCCESS); } @@ -515,13 +594,14 @@ int main (int argc, char **argv) break; default: confread_free(cfg); + cleanup(); exit(LSB_RC_SUCCESS); } } - /* save pid file in /var/run/starter.pid */ + /* save pid file in /var/run/starter[.daemon_name].pid */ { - FILE *fd = fopen(STARTER_PID_FILE, "w"); + FILE *fd = fopen(starter_pid_file, "w"); if (fd) { @@ -576,7 +656,8 @@ int main (int argc, char **argv) } starter_netkey_cleanup(); confread_free(cfg); - unlink(STARTER_PID_FILE); + unlink(starter_pid_file); + cleanup(); DBG1(DBG_APP, "ipsec starter stopped"); close_log(); exit(LSB_RC_SUCCESS); @@ -709,13 +790,13 @@ int main (int argc, char **argv) } /* - * Start charon + * Start daemon */ if (_action_ & FLAG_ACTION_START_CHARON) { if (cfg->setup.charonstart && !starter_charon_pid()) { - DBG2(DBG_APP, "Attempting to start charon..."); + DBG2(DBG_APP, "Attempting to start %s...", daemon_name); if (starter_start_charon(cfg, no_fork, attach_gdb)) { /* schedule next try */ @@ -807,7 +888,8 @@ int main (int argc, char **argv) /* * Wait for something to happen */ - if (pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL, + if (!_action_ && + pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL, &action.sa_mask) == 0) { /* timeout -> auto_update */ -- cgit v1.2.3 From 559fe48c5040788c5d8135f00905afb16e5ccaf7 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 18 May 2012 14:09:24 +0200 Subject: 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. --- src/Makefile.am | 4 + src/charon-tkm/.gitignore | 1 + src/charon-tkm/Makefile.am | 63 ++++++ src/charon-tkm/build_charon.gpr | 15 ++ src/charon-tkm/build_common.gpr | 10 + src/charon-tkm/build_tests.gpr | 14 ++ src/charon-tkm/src/charon-tkm.c | 330 ++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/.gitignore | 1 + src/charon-tkm/src/tkm/tkm.c | 67 +++++++ src/charon-tkm/src/tkm/tkm.h | 54 ++++++ src/charon-tkm/src/tkm/tkm_id_manager.c | 176 +++++++++++++++++ src/charon-tkm/src/tkm/tkm_id_manager.h | 79 ++++++++ src/charon-tkm/src/tkm/tkm_nonceg.c | 71 +++++++ src/charon-tkm/src/tkm/tkm_nonceg.h | 42 ++++ src/charon-tkm/tests/.gitignore | 1 + src/charon-tkm/tests/id_manager_tests.c | 131 +++++++++++++ src/charon-tkm/tests/nonceg_tests.c | 92 +++++++++ src/charon-tkm/tests/test_runner.c | 36 ++++ src/charon-tkm/tests/test_runner.h | 25 +++ 19 files changed, 1212 insertions(+) create mode 100644 src/charon-tkm/.gitignore create mode 100644 src/charon-tkm/Makefile.am create mode 100644 src/charon-tkm/build_charon.gpr create mode 100644 src/charon-tkm/build_common.gpr create mode 100644 src/charon-tkm/build_tests.gpr create mode 100644 src/charon-tkm/src/charon-tkm.c create mode 100644 src/charon-tkm/src/tkm/.gitignore create mode 100644 src/charon-tkm/src/tkm/tkm.c create mode 100644 src/charon-tkm/src/tkm/tkm.h create mode 100644 src/charon-tkm/src/tkm/tkm_id_manager.c create mode 100644 src/charon-tkm/src/tkm/tkm_id_manager.h create mode 100644 src/charon-tkm/src/tkm/tkm_nonceg.c create mode 100644 src/charon-tkm/src/tkm/tkm_nonceg.h create mode 100644 src/charon-tkm/tests/.gitignore create mode 100644 src/charon-tkm/tests/id_manager_tests.c create mode 100644 src/charon-tkm/tests/nonceg_tests.c create mode 100644 src/charon-tkm/tests/test_runner.c create mode 100644 src/charon-tkm/tests/test_runner.h (limited to 'src') 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 . + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +/** + * 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 . + * + * 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 . + * + * 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 . + * + * 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 +#include +#include + +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 . + * + * 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 + +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 . + * + * 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 . + * + * 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 + +/** + * 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 . + * + * 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 +#include + +#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 . + * + * 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 +#include + +#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 . + * + * 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 + +#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 . + * + * 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 + +TCase *make_id_manager_tests(void); +TCase *make_nonceg_tests(void); + +#endif /** TEST_RUNNER_H_ */ -- cgit v1.2.3 From 3d2746309e24f232e24687287d9e63d0dde1cadf Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 7 Jun 2012 17:45:34 +0200 Subject: Initialize TKM client library in tkm.c --- src/charon-tkm/src/charon-tkm.c | 12 ++++++++---- src/charon-tkm/src/tkm/tkm.c | 21 +++++++++++++++++++++ src/charon-tkm/tests/test_runner.c | 10 ++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 8731d7831..3e52fa47d 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -32,7 +32,7 @@ #include #include -#include +#include "tkm.h" /** * PID file, in which charon-tkm stores its process id @@ -294,8 +294,12 @@ int main(int argc, char *argv[]) goto deinit; } - /* initialize TKM client lib */ - tkmlib_init(); + /* initialize TKM client */ + if (!tkm_init()) + { + DBG1(DBG_DMN, "init of TKM client failed - aborting %s", dmn_name); + goto deinit; + } /* add handler for SEGV and ILL, * INT and TERM are handled by sigwait() in run() */ @@ -320,11 +324,11 @@ int main(int argc, char *argv[]) unlink_pidfile(); status = 0; - tkmlib_final(); deinit: libcharon_deinit(); libhydra_deinit(); library_deinit(); + tkm_deinit(); return status; } diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 1e61f882b..ebff089e5 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -14,8 +14,13 @@ * for more details. */ +#include +#include + #include "tkm.h" +#define IKE_SOCKET "/tmp/tkm.rpc.ike" + typedef struct private_tkm_t private_tkm_t; /** @@ -41,6 +46,20 @@ bool tkm_init() { private_tkm_t *this; + /* initialize TKM client library */ + tkmlib_init(); + if (ike_init(IKE_SOCKET) != TKM_OK) + { + tkmlib_final(); + return FALSE; + } + + if (ike_tkm_reset() != TKM_OK) + { + tkmlib_final(); + return FALSE; + } + INIT(this, .public = { .idmgr = tkm_id_manager_create(), @@ -62,6 +81,8 @@ void tkm_deinit() } private_tkm_t *this = (private_tkm_t*)tkm; this->public.idmgr->destroy(this->public.idmgr); + + tkmlib_final(); free(this); tkm = NULL; } diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index 61c252416..c16ad35b1 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -14,12 +14,17 @@ * for more details. */ -#include - +#include "tkm.h" #include "test_runner.h" int main(void) { + if (!tkm_init()) + { + fprintf(stderr, "Could not connect to TKM, aborting tests\n"); + return EXIT_FAILURE; + } + int number_failed; Suite *s = suite_create("TKM tests"); suite_add_tcase(s, make_id_manager_tests()); @@ -30,6 +35,7 @@ int main(void) srunner_run_all(sr, CK_NORMAL); number_failed = srunner_ntests_failed(sr); + tkm_deinit(); srunner_free(sr); return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -- cgit v1.2.3 From 8e95bf455dda5fd528065167617a33a8251ee35f Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 12 Jun 2012 11:05:14 +0200 Subject: tkm_nonceg: Return nonce generated by TKM --- src/charon-tkm/src/tkm/tkm_nonceg.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c index 1a83a5b16..9ac32a7c7 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.c +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -16,6 +16,9 @@ #include "tkm_nonceg.h" +#include +#include + typedef struct private_tkm_nonceg_t private_tkm_nonceg_t; /** @@ -33,7 +36,16 @@ struct private_tkm_nonceg_t { 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. + nonce_type nonce; + + /* request nonce from TKM, the context is not yet used */ + const result_type result = ike_nc_create(1, size, &nonce); + if (result != TKM_OK) + { + return FALSE; + } + + memcpy(buffer, &nonce.data, size); return TRUE; } -- cgit v1.2.3 From d51305aa3f2ff5949a10612d443f0d88b51a48ee Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 12 Jun 2012 14:39:33 +0200 Subject: charon-tkm: Register tkm nonce generator --- src/charon-tkm/Makefile.am | 1 - src/charon-tkm/src/charon-tkm.c | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 44586dc4a..94216cadb 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -27,7 +27,6 @@ PLUGINS = \ gmp \ hmac \ kernel-netlink \ - nonce \ pem \ pkcs1 \ pkcs8 \ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 3e52fa47d..c9c27ba1c 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -33,6 +33,7 @@ #include #include "tkm.h" +#include "tkm_nonceg.h" /** * PID file, in which charon-tkm stores its process id @@ -267,6 +268,14 @@ int main(int argc, char *argv[]) DBG1(DBG_DMN, "Starting charon with TKM backend (strongSwan "VERSION")"); + /* register TKM specific plugins */ + static plugin_feature_t features[] = { + PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), + PLUGIN_PROVIDE(NONCE_GEN) + }; + lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, + countof(features), TRUE); + /* initialize daemon */ if (!charon->initialize(charon, PLUGINS)) { -- cgit v1.2.3 From f3cd7f50dea0bfc9806322eeacfae6b19a350272 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 24 Jul 2012 10:40:26 +0200 Subject: Add initial TKM Diffie-Hellman implementation The tkm_diffie_hellman_t plugin acquires a DH context from the Trusted Key Manager and uses it to get a DH public value and the calculated shared secret. Proper context handling is still missing though, the plugin currently uses context ID 1. The get_shared_secret function will be removed as soon as the TKM specific keymat is ready. --- src/charon-tkm/Makefile.am | 1 - src/charon-tkm/src/charon-tkm.c | 6 +- src/charon-tkm/src/tkm/tkm_diffie_hellman.c | 126 ++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_diffie_hellman.h | 43 ++++++++++ src/charon-tkm/tests/diffie_hellman_tests.c | 58 +++++++++++++ src/charon-tkm/tests/test_runner.c | 1 + src/charon-tkm/tests/test_runner.h | 1 + 7 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 src/charon-tkm/src/tkm/tkm_diffie_hellman.c create mode 100644 src/charon-tkm/src/tkm/tkm_diffie_hellman.h create mode 100644 src/charon-tkm/tests/diffie_hellman_tests.c (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 94216cadb..1b5dfdf2b 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -24,7 +24,6 @@ BUILD_OPTS = \ PLUGINS = \ aes \ constraints \ - gmp \ hmac \ kernel-netlink \ pem \ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index c9c27ba1c..bf8745aec 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -34,6 +34,7 @@ #include "tkm.h" #include "tkm_nonceg.h" +#include "tkm_diffie_hellman.h" /** * PID file, in which charon-tkm stores its process id @@ -271,7 +272,10 @@ int main(int argc, char *argv[]) /* register TKM specific plugins */ static plugin_feature_t features[] = { PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), - PLUGIN_PROVIDE(NONCE_GEN) + PLUGIN_PROVIDE(NONCE_GEN), + PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), + PLUGIN_PROVIDE(DH, MODP_3072_BIT), + PLUGIN_PROVIDE(DH, MODP_4096_BIT), }; lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE); diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c new file mode 100644 index 000000000..fa5b0c5a7 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c @@ -0,0 +1,126 @@ +/* + * 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 . + * + * 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 +#include + +#include "tkm_diffie_hellman.h" + +#include + +typedef struct private_tkm_diffie_hellman_t private_tkm_diffie_hellman_t; + +/** + * Private data of a tkm_diffie_hellman_t object. + */ +struct private_tkm_diffie_hellman_t { + /** + * Public tkm_diffie_hellman_t interface. + */ + tkm_diffie_hellman_t public; + + /** + * Diffie Hellman group number. + */ + u_int16_t group; + + /** + * Diffie Hellman public value. + */ + dh_pubvalue_type pubvalue; +}; + +METHOD(diffie_hellman_t, get_my_public_value, void, + private_tkm_diffie_hellman_t *this, chunk_t *value) +{ + *value = chunk_alloc(this->pubvalue.size); + memcpy(value->ptr, &this->pubvalue.data, value->len); +} + +METHOD(diffie_hellman_t, get_shared_secret, status_t, + private_tkm_diffie_hellman_t *this, chunk_t *secret) +{ + dh_key_type shared_secret; + if (ike_dh_get_shared_secret(1, &shared_secret) != TKM_OK) + { + return FAILED; + } + + *secret = chunk_alloc(shared_secret.size); + memcpy(secret->ptr, &shared_secret.data, secret->len); + return SUCCESS; +} + + +METHOD(diffie_hellman_t, set_other_public_value, void, + private_tkm_diffie_hellman_t *this, chunk_t value) +{ + // TODO: unvoid this function + + dh_pubvalue_type othervalue; + othervalue.size = value.len; + memcpy(&othervalue.data, value.ptr, value.len); + + ike_dh_generate_key(1, othervalue); +} + +METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, + private_tkm_diffie_hellman_t *this) +{ + return this->group; +} + +METHOD(diffie_hellman_t, destroy, void, + private_tkm_diffie_hellman_t *this) +{ + // TODO: unvoid this function + + free(this); + if (ike_dh_reset(1) != TKM_OK) + { + DBG1(DBG_LIB, "resetting DH context 1 failed"); + } +} + +/* + * Described in header. + */ +tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group) +{ + private_tkm_diffie_hellman_t *this; + + INIT(this, + .public = { + .dh = { + .get_shared_secret = _get_shared_secret, + .set_other_public_value = _set_other_public_value, + .get_my_public_value = _get_my_public_value, + .get_dh_group = _get_dh_group, + .destroy = _destroy, + }, + }, + ); + + if (ike_dh_create(1, group, &this->pubvalue) != TKM_OK) + { + free(this); + return NULL; + } + + this->group = group; + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.h b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h new file mode 100644 index 000000000..25d196764 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h @@ -0,0 +1,43 @@ +/* + * 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 . + * + * 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_DIFFIE_HELLMAN_H_ +#define TKM_DIFFIE_HELLMAN_H_ + +typedef struct tkm_diffie_hellman_t tkm_diffie_hellman_t; + +#include + +/** + * diffie_hellman_t implementation using the trusted key manager. + */ +struct tkm_diffie_hellman_t { + + /** + * Implements diffie_hellman_t interface. + */ + diffie_hellman_t dh; +}; + +/** + * Creates a new tkm_diffie_hellman_t object. + * + * @param group Diffie Hellman group number to use + * @return tkm_diffie_hellman_t object, NULL if not supported + */ +tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group); + +#endif /** TKM_DIFFIE_HELLMAN_H_ */ diff --git a/src/charon-tkm/tests/diffie_hellman_tests.c b/src/charon-tkm/tests/diffie_hellman_tests.c new file mode 100644 index 000000000..c2e905e76 --- /dev/null +++ b/src/charon-tkm/tests/diffie_hellman_tests.c @@ -0,0 +1,58 @@ +/* + * 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 . + * + * 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 + +#include "tkm_diffie_hellman.h" + +START_TEST(test_dh_creation) +{ + tkm_diffie_hellman_t *dh = NULL; + + dh = tkm_diffie_hellman_create(MODP_768_BIT); + fail_if(dh, "MODP_768 created"); + + dh = tkm_diffie_hellman_create(MODP_4096_BIT); + fail_if(!dh, "MODP_4096 not created"); + + dh->dh.destroy(&dh->dh); +} +END_TEST + +START_TEST(test_dh_get_my_pubvalue) +{ + tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT); + fail_if(!dh, "Unable to create DH"); + + chunk_t value; + dh->dh.get_my_public_value(&dh->dh, &value); + dh->dh.destroy(&dh->dh); + + fail_if(value.ptr == NULL, "Pubvalue is NULL"); + fail_if(value.len != 512, "Pubvalue size mismatch"); + + chunk_free(&value); +} +END_TEST + +TCase *make_diffie_hellman_tests(void) +{ + TCase *tc = tcase_create("Diffie-Hellman tests"); + tcase_add_test(tc, test_dh_creation); + tcase_add_test(tc, test_dh_get_my_pubvalue); + + return tc; +} diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index c16ad35b1..5c795f8d6 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -29,6 +29,7 @@ int main(void) Suite *s = suite_create("TKM tests"); suite_add_tcase(s, make_id_manager_tests()); suite_add_tcase(s, make_nonceg_tests()); + suite_add_tcase(s, make_diffie_hellman_tests()); SRunner *sr = srunner_create(s); diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h index 3d15fb99f..1de47d510 100644 --- a/src/charon-tkm/tests/test_runner.h +++ b/src/charon-tkm/tests/test_runner.h @@ -21,5 +21,6 @@ TCase *make_id_manager_tests(void); TCase *make_nonceg_tests(void); +TCase *make_diffie_hellman_tests(void); #endif /** TEST_RUNNER_H_ */ -- cgit v1.2.3 From c38459d77d4400f4106781fdbf071c7d16793288 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 7 Aug 2012 17:46:45 +0200 Subject: Use id manager to acquire nonce context id --- src/charon-tkm/src/tkm/tkm_nonceg.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c index 9ac32a7c7..90b033f9f 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.c +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -14,11 +14,12 @@ * for more details. */ -#include "tkm_nonceg.h" - #include #include +#include "tkm.h" +#include "tkm_nonceg.h" + typedef struct private_tkm_nonceg_t private_tkm_nonceg_t; /** @@ -31,16 +32,18 @@ struct private_tkm_nonceg_t { */ tkm_nonceg_t public; + /** + * Context id. + */ + nc_id_type context_id; + }; METHOD(nonce_gen_t, get_nonce, bool, private_tkm_nonceg_t *this, size_t size, u_int8_t *buffer) { nonce_type nonce; - - /* request nonce from TKM, the context is not yet used */ - const result_type result = ike_nc_create(1, size, &nonce); - if (result != TKM_OK) + if (ike_nc_create(this->context_id, size, &nonce) != TKM_OK) { return FALSE; } @@ -77,7 +80,14 @@ tkm_nonceg_t *tkm_nonceg_create() .destroy = _destroy, }, }, + .context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_NONCE), ); + if (!this->context_id) + { + free(this); + return NULL; + } + return &this->public; } -- cgit v1.2.3 From 65a777f7fb653ae32ae9accbce35d38f10e25225 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 8 Aug 2012 16:56:30 +0200 Subject: Add TKM_CTX_DH (Diffie-Hellman context) to id manager --- src/charon-tkm/src/tkm/tkm_id_manager.c | 7 ++++--- src/charon-tkm/src/tkm/tkm_id_manager.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 4a1afe37f..806a8741b 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -20,9 +20,10 @@ #include #include -ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_NONCE, - "NONCE_CONTEXT"); -ENUM_END(tkm_context_kind_names, TKM_CTX_NONCE); +ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH, + "NONCE_CONTEXT", + "DH_CONTEXT"); +ENUM_END(tkm_context_kind_names, TKM_CTX_DH); typedef struct private_tkm_id_manager_t private_tkm_id_manager_t; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index f348b6d57..9842979dc 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -28,6 +28,8 @@ typedef enum tkm_context_kind_t tkm_context_kind_t; enum tkm_context_kind_t { /** Nonce context */ TKM_CTX_NONCE, + /** Diffie-Hellman context */ + TKM_CTX_DH, /** helper to determine the number of elements in this enum */ TKM_CTX_MAX, -- cgit v1.2.3 From 49c513c1d9361e21836003ed851a0b829a0e2a33 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 8 Aug 2012 16:59:19 +0200 Subject: Use id manager to acquire DH context id --- src/charon-tkm/src/tkm/tkm_diffie_hellman.c | 32 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c index fa5b0c5a7..21378da5a 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c @@ -17,6 +17,7 @@ #include #include +#include "tkm.h" #include "tkm_diffie_hellman.h" #include @@ -27,6 +28,7 @@ typedef struct private_tkm_diffie_hellman_t private_tkm_diffie_hellman_t; * Private data of a tkm_diffie_hellman_t object. */ struct private_tkm_diffie_hellman_t { + /** * Public tkm_diffie_hellman_t interface. */ @@ -41,6 +43,12 @@ struct private_tkm_diffie_hellman_t { * Diffie Hellman public value. */ dh_pubvalue_type pubvalue; + + /** + * Context id. + */ + dh_id_type context_id; + }; METHOD(diffie_hellman_t, get_my_public_value, void, @@ -54,7 +62,7 @@ METHOD(diffie_hellman_t, get_shared_secret, status_t, private_tkm_diffie_hellman_t *this, chunk_t *secret) { dh_key_type shared_secret; - if (ike_dh_get_shared_secret(1, &shared_secret) != TKM_OK) + if (ike_dh_get_shared_secret(this->context_id, &shared_secret) != TKM_OK) { return FAILED; } @@ -74,7 +82,7 @@ METHOD(diffie_hellman_t, set_other_public_value, void, othervalue.size = value.len; memcpy(&othervalue.data, value.ptr, value.len); - ike_dh_generate_key(1, othervalue); + ike_dh_generate_key(this->context_id, othervalue); } METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, @@ -86,13 +94,13 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, METHOD(diffie_hellman_t, destroy, void, private_tkm_diffie_hellman_t *this) { - // TODO: unvoid this function - - free(this); - if (ike_dh_reset(1) != TKM_OK) + if (ike_dh_reset(this->context_id) != TKM_OK) { - DBG1(DBG_LIB, "resetting DH context 1 failed"); + DBG1(DBG_LIB, "failed to reset DH context %d", this->context_id); } + + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_DH, this->context_id); + free(this); } /* @@ -112,15 +120,21 @@ tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group) .destroy = _destroy, }, }, + .group = group, + .context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_DH), ); - if (ike_dh_create(1, group, &this->pubvalue) != TKM_OK) + if (!this->context_id) { free(this); return NULL; } - this->group = group; + if (ike_dh_create(this->context_id, group, &this->pubvalue) != TKM_OK) + { + free(this); + return NULL; + } return &this->public; } -- cgit v1.2.3 From 7aa573a50e06fa02c78740abaa4911b35d635b18 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 9 Aug 2012 12:47:58 +0200 Subject: id_manager: Use array of bool instead of list Instead of storing the acquired context ids in a linked list, use an array of booleans for the job. A boolean value of true in the array designates an available context id. --- src/charon-tkm/src/tkm/tkm_id_manager.c | 65 ++++++++++++--------------------- src/charon-tkm/tests/id_manager_tests.c | 18 +++++++++ 2 files changed, 42 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 806a8741b..5a657fa43 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -20,6 +20,8 @@ #include #include +#define TKM_LIMIT 100 + ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH, "NONCE_CONTEXT", "DH_CONTEXT"); @@ -38,14 +40,9 @@ struct private_tkm_id_manager_t { tkm_id_manager_t public; /** - * Next free context id values. - */ - int nextids[TKM_CTX_MAX]; - - /** - * Per-kind list of acquired context ids + * Per-kind array of free context ids */ - linked_list_t *ctxids[TKM_CTX_MAX]; + bool* ctxids[TKM_CTX_MAX]; /** * rwlocks for context id lists @@ -69,8 +66,7 @@ static bool is_valid_kind(const tkm_context_kind_t kind) 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; + int j, id = 0; if (!is_valid_kind(kind)) { @@ -80,13 +76,15 @@ METHOD(tkm_id_manager_t, acquire_id, int, } 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]++; - + for (j = 0; j < TKM_LIMIT; j++) + { + if (this->ctxids[kind][j]) + { + this->ctxids[kind][j] = false; + id = j + 1; + break; + } + } this->locks[kind]->unlock(this->locks[kind]); if (!id) @@ -102,9 +100,7 @@ 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; + const int idx = id - 1; if (!is_valid_kind(kind)) { @@ -114,25 +110,9 @@ METHOD(tkm_id_manager_t, release_id, bool, } 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->ctxids[kind][idx] = true; 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; } @@ -141,10 +121,9 @@ 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]); + free(this->ctxids[i]); this->locks[i]->destroy(this->locks[i]); } free(this); @@ -156,7 +135,7 @@ METHOD(tkm_id_manager_t, destroy, void, tkm_id_manager_t *tkm_id_manager_create() { private_tkm_id_manager_t *this; - int i; + int i, j; INIT(this, .public = { @@ -168,9 +147,13 @@ tkm_id_manager_t *tkm_id_manager_create() for (i = 0; i < TKM_CTX_MAX; i++) { - this->nextids[i] = 1; - this->ctxids[i] = linked_list_create(); + this->ctxids[i] = malloc(TKM_LIMIT * sizeof(bool)); this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); + for (j = 0; j < TKM_LIMIT; j++) + { + /* available id slots are in true state (is_available) */ + this->ctxids[i][j] = true; + } } return &this->public; diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index 0942c299a..a71727a38 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -66,6 +66,23 @@ START_TEST(test_acquire_id_invalid_kind) } END_TEST +START_TEST(test_acquire_id_same) +{ + int id1 = 0, id2 = 0; + tkm_id_manager_t *idmgr = tkm_id_manager_create(); + + id1 = idmgr->acquire_id(idmgr, TKM_CTX_NONCE); + fail_unless(id1 > 0, "Unable to acquire first id"); + + /* Acquire another id, must be different than first */ + id2 = idmgr->acquire_id(idmgr, TKM_CTX_NONCE); + fail_unless(id2 > 0, "Unable to acquire second id"); + fail_unless(id1 != id2, "Same id received twice"); + + idmgr->destroy(idmgr); +} +END_TEST + START_TEST(test_release_id) { int i, id = 0; @@ -123,6 +140,7 @@ TCase *make_id_manager_tests(void) 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_acquire_id_same); tcase_add_test(tc, test_release_id); tcase_add_test(tc, test_release_id_invalid_kind); tcase_add_test(tc, test_release_id_nonexistent); -- cgit v1.2.3 From ef5372395adb54f70b552ea87cec430f919f456c Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 9 Aug 2012 15:12:40 +0200 Subject: Request limits from TKM on init --- src/charon-tkm/src/tkm/tkm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index ebff089e5..e913ddbdf 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -46,6 +46,14 @@ bool tkm_init() { private_tkm_t *this; + active_requests_type max_requests; + nc_id_type nc; + dh_id_type dh; + cc_id_type cc; + ae_id_type ae; + isa_id_type isa; + esa_id_type esa; + /* initialize TKM client library */ tkmlib_init(); if (ike_init(IKE_SOCKET) != TKM_OK) @@ -60,6 +68,13 @@ bool tkm_init() return FALSE; } + /* get limits from tkm */ + if (ike_tkm_limits(&max_requests, &nc, &dh, &cc, &ae, &isa, &esa) != TKM_OK) + { + tkmlib_final(); + return FALSE; + } + INIT(this, .public = { .idmgr = tkm_id_manager_create(), -- cgit v1.2.3 From 50e35e66d22f6d50d016ff322a53623c82969777 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 9 Aug 2012 15:18:05 +0200 Subject: Pass context limits on to id manager --- src/charon-tkm/src/tkm/tkm.c | 5 ++++- src/charon-tkm/src/tkm/tkm_id_manager.c | 2 +- src/charon-tkm/src/tkm/tkm_id_manager.h | 9 +++++++-- src/charon-tkm/tests/id_manager_tests.c | 17 +++++++++-------- 4 files changed, 21 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index e913ddbdf..f78d49be5 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -75,9 +75,12 @@ bool tkm_init() return FALSE; } + /* only nonce and DH context limits are currently needed */ + const tkm_limits_t limits = {nc, dh}; + INIT(this, .public = { - .idmgr = tkm_id_manager_create(), + .idmgr = tkm_id_manager_create(limits), }, ); tkm = &this->public; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 5a657fa43..8426a2cef 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -132,7 +132,7 @@ METHOD(tkm_id_manager_t, destroy, void, /* * see header file */ -tkm_id_manager_t *tkm_id_manager_create() +tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) { private_tkm_id_manager_t *this; int i, j; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 9842979dc..9fbdb2d72 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -40,6 +40,11 @@ enum tkm_context_kind_t { */ extern enum_name_t *tkm_context_kind_names; +/** + * TKM context limits. + */ +typedef uint64_t tkm_limits_t[TKM_CTX_MAX]; + /** * The tkm id manager hands out context ids for all context kinds (e.g. nonce). */ @@ -74,8 +79,8 @@ struct tkm_id_manager_t { }; /** - * Create a tkm id manager instance. + * Create a tkm id manager instance using the given context limits. */ -tkm_id_manager_t *tkm_id_manager_create(); +tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits); #endif /** TKM_ID_MANAGER_H_ */ diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index a71727a38..86e80aee0 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -14,16 +14,17 @@ * for more details. */ -#include #include #include "tkm_id_manager.h" +static const tkm_limits_t limits = {125, 100}; + START_TEST(test_id_mgr_creation) { tkm_id_manager_t *idmgr = NULL; - idmgr = tkm_id_manager_create(); + idmgr = tkm_id_manager_create(limits); fail_if(idmgr == NULL, "Error creating tkm id manager"); idmgr->destroy(idmgr); @@ -33,7 +34,7 @@ END_TEST START_TEST(test_acquire_id) { int i, id = 0; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); for (i = 0; i < TKM_CTX_MAX; i++) { @@ -51,7 +52,7 @@ END_TEST START_TEST(test_acquire_id_invalid_kind) { int id = 0; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); id = idmgr->acquire_id(idmgr, TKM_CTX_MAX); fail_unless(id == 0, "Acquired id for invalid context kind %d", TKM_CTX_MAX); @@ -69,7 +70,7 @@ END_TEST START_TEST(test_acquire_id_same) { int id1 = 0, id2 = 0; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); id1 = idmgr->acquire_id(idmgr, TKM_CTX_NONCE); fail_unless(id1 > 0, "Unable to acquire first id"); @@ -87,7 +88,7 @@ START_TEST(test_release_id) { int i, id = 0; bool released = false; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); for (i = 0; i < TKM_CTX_MAX; i++) { @@ -107,7 +108,7 @@ END_TEST START_TEST(test_release_id_invalid_kind) { bool released = TRUE; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); released = idmgr->release_id(idmgr, TKM_CTX_MAX, 1); fail_if(released, "Released id for invalid context kind %d", TKM_CTX_MAX); @@ -125,7 +126,7 @@ END_TEST START_TEST(test_release_id_nonexistent) { bool released = FALSE; - tkm_id_manager_t *idmgr = tkm_id_manager_create(); + tkm_id_manager_t *idmgr = tkm_id_manager_create(limits); released = idmgr->release_id(idmgr, TKM_CTX_NONCE, 1); fail_unless(released, "Release of nonexistent id failed"); -- cgit v1.2.3 From 84967b44392cd61b2c251086d07c0685e42f56b8 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 9 Aug 2012 16:13:55 +0200 Subject: id_manager: Use limits given by TKM --- src/charon-tkm/src/tkm/tkm_id_manager.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 8426a2cef..f069e0eba 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -44,6 +44,11 @@ struct private_tkm_id_manager_t { */ bool* ctxids[TKM_CTX_MAX]; + /** + * Per-kind context limits. + */ + tkm_limits_t limits; + /** * rwlocks for context id lists */ @@ -66,7 +71,8 @@ static bool is_valid_kind(const tkm_context_kind_t kind) METHOD(tkm_id_manager_t, acquire_id, int, private_tkm_id_manager_t * const this, const tkm_context_kind_t kind) { - int j, id = 0; + int id = 0; + uint64_t j; if (!is_valid_kind(kind)) { @@ -76,7 +82,7 @@ METHOD(tkm_id_manager_t, acquire_id, int, } this->locks[kind]->write_lock(this->locks[kind]); - for (j = 0; j < TKM_LIMIT; j++) + for (j = 0; j < this->limits[kind]; j++) { if (this->ctxids[kind][j]) { @@ -135,7 +141,8 @@ METHOD(tkm_id_manager_t, destroy, void, tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) { private_tkm_id_manager_t *this; - int i, j; + int i; + uint64_t j; INIT(this, .public = { @@ -147,13 +154,16 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) for (i = 0; i < TKM_CTX_MAX; i++) { - this->ctxids[i] = malloc(TKM_LIMIT * sizeof(bool)); + this->limits[i] = limits[i]; + this->ctxids[i] = malloc(limits[i] * sizeof(bool)); this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); - for (j = 0; j < TKM_LIMIT; j++) + for (j = 0; j < limits[i]; j++) { /* available id slots are in true state (is_available) */ this->ctxids[i][j] = true; } + DBG2(DBG_LIB, "%N initialized, %llu slot(s)", + tkm_context_kind_names, i, limits[i]); } return &this->public; -- cgit v1.2.3 From 5b3bcdfadaa6c305d09af459c7e568b9b6854bef Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 21 Aug 2012 12:17:05 +0200 Subject: Add skeleton for TKM keymat variant --- src/charon-tkm/src/charon-tkm.c | 5 ++ src/charon-tkm/src/tkm/tkm_keymat.c | 132 ++++++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_keymat.h | 119 ++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_keymat.c create mode 100644 src/charon-tkm/src/tkm/tkm_keymat.h (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index bf8745aec..e102b4e0d 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -31,10 +31,12 @@ #include #include #include +#include #include "tkm.h" #include "tkm_nonceg.h" #include "tkm_diffie_hellman.h" +#include "tkm_keymat.h" /** * PID file, in which charon-tkm stores its process id @@ -280,6 +282,9 @@ int main(int argc, char *argv[]) lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE); + /* register TKM keymat variant */ + keymat_register_constructor(IKEV2, (keymat_constructor_t)tkm_keymat_create); + /* initialize daemon */ if (!charon->initialize(charon, PLUGINS)) { diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c new file mode 100644 index 000000000..cdc6800f0 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -0,0 +1,132 @@ +/* + * 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 . + * + * 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 + +#include "tkm_keymat.h" + +typedef struct private_tkm_keymat_t private_tkm_keymat_t; + +/** + * Private data of a keymat_t object. + */ +struct private_tkm_keymat_t { + + /** + * Public tkm_keymat_t interface. + */ + tkm_keymat_t public; + +}; + +METHOD(keymat_t, get_version, ike_version_t, + private_tkm_keymat_t *this) +{ + return IKEV2; +} + +METHOD(keymat_t, create_dh, diffie_hellman_t*, + private_tkm_keymat_t *this, diffie_hellman_group_t group) +{ + return lib->crypto->create_dh(lib->crypto, group); +} + +METHOD(keymat_t, create_nonce_gen, nonce_gen_t*, + private_tkm_keymat_t *this) +{ + return lib->crypto->create_nonce_gen(lib->crypto); +} + +METHOD(tkm_keymat_t, derive_ike_keys, bool, + private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, + pseudo_random_function_t rekey_function, chunk_t rekey_skd) +{ + DBG1(DBG_IKE, "deriving IKE keys"); + return FALSE; +} + +METHOD(tkm_keymat_t, derive_child_keys, bool, + private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, + chunk_t *encr_r, chunk_t *integ_r) +{ + DBG1(DBG_CHD, "deriving child keys"); + return FALSE; +} + +METHOD(keymat_t, get_aead, aead_t*, + private_tkm_keymat_t *this, bool in) +{ + DBG1(DBG_IKE, "get_aead called"); + return NULL; +} + +METHOD(tkm_keymat_t, get_auth_octets, bool, + private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, + chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) +{ + DBG1(DBG_IKE, "returning auth octets"); + return FALSE; +} + +METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t, + private_tkm_keymat_t *this, chunk_t *skd) +{ + DBG1(DBG_IKE, "returning skd"); + return PRF_UNDEFINED; +} + +METHOD(tkm_keymat_t, get_psk_sig, bool, + private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, + chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) +{ + DBG1(DBG_IKE, "returning PSK signature"); + return FALSE; +} + +METHOD(keymat_t, destroy, void, + private_tkm_keymat_t *this) +{ + free(this); +} + +/** + * See header. + */ +tkm_keymat_t *tkm_keymat_create(bool initiator) +{ + private_tkm_keymat_t *this; + + INIT(this, + .public = { + .keymat = { + .get_version = _get_version, + .create_dh = _create_dh, + .create_nonce_gen = _create_nonce_gen, + .get_aead = _get_aead, + .destroy = _destroy, + }, + .derive_ike_keys = _derive_ike_keys, + .derive_child_keys = _derive_child_keys, + .get_skd = _get_skd, + .get_auth_octets = _get_auth_octets, + .get_psk_sig = _get_psk_sig, + }, + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h new file mode 100644 index 000000000..2def71fb3 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -0,0 +1,119 @@ +/* + * 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 . + * + * 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_KEYMAT_H_ +#define TKM_KEYMAT_H_ + +#include + +typedef struct tkm_keymat_t tkm_keymat_t; + +/** + * Derivation and management of sensitive keying material, TKM variant. + */ +struct tkm_keymat_t { + + /** + * Implements keymat_t. + */ + keymat_t keymat; + + /** + * Use TKM to derive IKE key material. + * + * @param proposal selected algorithms + * @param dh diffie hellman key allocated by create_dh() + * @param nonce_i initiators nonce value + * @param nonce_r responders nonce value + * @param id IKE_SA identifier + * @param rekey_prf PRF of old SA if rekeying, PRF_UNDEFINED otherwise + * @param rekey_skd SKd of old SA if rekeying + * @return TRUE on success + */ + bool (*derive_ike_keys)(tkm_keymat_t *this, proposal_t *proposal, + diffie_hellman_t *dh, chunk_t nonce_i, + chunk_t nonce_r, ike_sa_id_t *id, + pseudo_random_function_t rekey_function, + chunk_t rekey_skd); + + /** + * Use TKM to derive child key material. + * + * @param proposal selected algorithms + * @param dh diffie hellman key allocated by create_dh(), or NULL + * @param nonce_i initiators nonce value + * @param nonce_r responders nonce value + * @param encr_i handle to initiators encryption key + * @param integ_i handle to initiators integrity key + * @param encr_r handle to responders encryption key + * @param integ_r handle to responders integrity key + * @return TRUE on success + */ + bool (*derive_child_keys)(tkm_keymat_t *this, + proposal_t *proposal, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, + chunk_t *encr_i, chunk_t *integ_i, + chunk_t *encr_r, chunk_t *integ_r); + + /** + * Use TKM to generate auth octets. + * + * @param verify TRUE to create for verfification, FALSE to sign + * @param ike_sa_init encoded ike_sa_init message + * @param nonce nonce value + * @param id identity + * @param reserved reserved bytes of id_payload + * @param octests chunk receiving allocated auth octets + * @return TRUE if octets created successfully + */ + bool (*get_auth_octets)(tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, + chunk_t nonce, identification_t *id, + char reserved[3], chunk_t *octets); + + /** + * Get SKd and PRF to derive keymat. + * + * @param skd chunk to write SKd to (internal data) + * @return PRF function to derive keymat + */ + pseudo_random_function_t (*get_skd)(tkm_keymat_t *this, chunk_t *skd); + + /** + * Build the shared secret signature used for PSK and EAP authentication. + * + * @param verify TRUE to create for verfification, FALSE to sign + * @param ike_sa_init encoded ike_sa_init message + * @param nonce nonce value + * @param secret optional secret to include into signature + * @param id identity + * @param reserved reserved bytes of id_payload + * @param sign chunk receiving allocated signature octets + * @return TRUE if signature created successfully + */ + bool (*get_psk_sig)(tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, + chunk_t nonce, chunk_t secret, + identification_t *id, char reserved[3], chunk_t *sig); +}; + +/** + * Create TKM keymat instance. + * + * @param initiator TRUE if we are the initiator + * @return keymat instance + */ +tkm_keymat_t *tkm_keymat_create(bool initiator); + +#endif /** KEYMAT_TKM_H_ */ -- cgit v1.2.3 From 1ee792f9ea06ecb01af019badbe1cbb1c260fc83 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 21 Aug 2012 12:38:50 +0200 Subject: Use ikev2 keymat proxy Forward incoming calls to default ikev2 keymat instance. This is needed to make a stepwise migration to TKM keymat possible. It will be removed once the corresponding parts are implemented in the TKM. --- src/charon-tkm/src/tkm/tkm_keymat.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index cdc6800f0..186f67b3a 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -15,6 +15,7 @@ */ #include +#include #include "tkm_keymat.h" @@ -30,6 +31,11 @@ struct private_tkm_keymat_t { */ tkm_keymat_t public; + /** + * IKEv2 keymat proxy (will be removed). + */ + keymat_v2_t *proxy; + }; METHOD(keymat_t, get_version, ike_version_t, @@ -56,7 +62,8 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { DBG1(DBG_IKE, "deriving IKE keys"); - return FALSE; + return this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, + nonce_r, id, rekey_function, rekey_skd); } METHOD(tkm_keymat_t, derive_child_keys, bool, @@ -65,14 +72,15 @@ METHOD(tkm_keymat_t, derive_child_keys, bool, chunk_t *encr_r, chunk_t *integ_r) { DBG1(DBG_CHD, "deriving child keys"); - return FALSE; + return this->proxy->derive_child_keys(this->proxy, proposal, dh, nonce_i, + nonce_r, encr_i, integ_i, encr_r, integ_r); } METHOD(keymat_t, get_aead, aead_t*, private_tkm_keymat_t *this, bool in) { - DBG1(DBG_IKE, "get_aead called"); - return NULL; + DBG1(DBG_IKE, "returning aead transform"); + return this->proxy->keymat.get_aead(&this->proxy->keymat, in); } METHOD(tkm_keymat_t, get_auth_octets, bool, @@ -80,14 +88,15 @@ METHOD(tkm_keymat_t, get_auth_octets, bool, chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) { DBG1(DBG_IKE, "returning auth octets"); - return FALSE; + return this->proxy->get_auth_octets(this->proxy, verify, ike_sa_init, nonce, + id, reserved, octets); } METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t, private_tkm_keymat_t *this, chunk_t *skd) { DBG1(DBG_IKE, "returning skd"); - return PRF_UNDEFINED; + return this->proxy->get_skd(this->proxy, skd); } METHOD(tkm_keymat_t, get_psk_sig, bool, @@ -95,7 +104,8 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) { DBG1(DBG_IKE, "returning PSK signature"); - return FALSE; + return this->proxy->get_psk_sig(this->proxy, verify, ike_sa_init, nonce, + secret, id, reserved, sig); } METHOD(keymat_t, destroy, void, @@ -126,6 +136,7 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, }, + .proxy = keymat_v2_create(initiator), ); return &this->public; -- cgit v1.2.3 From ebe592a393b175d274cc8ac3a7b25521d595622b Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 21 Aug 2012 15:29:30 +0200 Subject: id_manager: Use calloc instead of malloc This way we don't need to manually initialize the slot status; free slots are now indicated by 0 though. --- src/charon-tkm/src/tkm/tkm_id_manager.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index f069e0eba..8cafa4193 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -84,9 +84,9 @@ METHOD(tkm_id_manager_t, acquire_id, int, this->locks[kind]->write_lock(this->locks[kind]); for (j = 0; j < this->limits[kind]; j++) { - if (this->ctxids[kind][j]) + if (!this->ctxids[kind][j]) { - this->ctxids[kind][j] = false; + this->ctxids[kind][j] = true; id = j + 1; break; } @@ -116,7 +116,7 @@ METHOD(tkm_id_manager_t, release_id, bool, } this->locks[kind]->write_lock(this->locks[kind]); - this->ctxids[kind][idx] = true; + this->ctxids[kind][idx] = false; this->locks[kind]->unlock(this->locks[kind]); return TRUE; @@ -142,7 +142,6 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) { private_tkm_id_manager_t *this; int i; - uint64_t j; INIT(this, .public = { @@ -155,13 +154,8 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) for (i = 0; i < TKM_CTX_MAX; i++) { this->limits[i] = limits[i]; - this->ctxids[i] = malloc(limits[i] * sizeof(bool)); + this->ctxids[i] = calloc(limits[i], sizeof(bool)); this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); - for (j = 0; j < limits[i]; j++) - { - /* available id slots are in true state (is_available) */ - this->ctxids[i][j] = true; - } DBG2(DBG_LIB, "%N initialized, %llu slot(s)", tkm_context_kind_names, i, limits[i]); } -- cgit v1.2.3 From 601de9f36f0ed811d9af243c052a925b4bbca807 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 21 Aug 2012 14:31:13 +0200 Subject: Add context id getter to TKM nonce generator --- src/charon-tkm/src/tkm/tkm_nonceg.c | 7 +++++++ src/charon-tkm/src/tkm/tkm_nonceg.h | 9 +++++++++ src/charon-tkm/tests/nonceg_tests.c | 1 + 3 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c index 90b033f9f..7079412cd 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.c +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -65,6 +65,12 @@ METHOD(nonce_gen_t, destroy, void, free(this); } +METHOD(tkm_nonceg_t, get_id, nc_id_type, + private_tkm_nonceg_t *this) +{ + return this->context_id; +} + /* * Described in header. */ @@ -79,6 +85,7 @@ tkm_nonceg_t *tkm_nonceg_create() .allocate_nonce = _allocate_nonce, .destroy = _destroy, }, + .get_id = _get_id, }, .context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_NONCE), ); diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.h b/src/charon-tkm/src/tkm/tkm_nonceg.h index 907890bbd..25ec48a64 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.h +++ b/src/charon-tkm/src/tkm/tkm_nonceg.h @@ -20,6 +20,7 @@ typedef struct tkm_nonceg_t tkm_nonceg_t; #include +#include /** * nonce_gen_t implementation using the trusted key manager. @@ -30,6 +31,14 @@ struct tkm_nonceg_t { * Implements nonce_gen_t. */ nonce_gen_t nonce_gen; + + /** + * Get nonce context id. + * + * @return context id of this nonce generator. + */ + nc_id_type (*get_id)(tkm_nonceg_t * const this); + }; /** diff --git a/src/charon-tkm/tests/nonceg_tests.c b/src/charon-tkm/tests/nonceg_tests.c index 202a9e5c7..3a1effab8 100644 --- a/src/charon-tkm/tests/nonceg_tests.c +++ b/src/charon-tkm/tests/nonceg_tests.c @@ -26,6 +26,7 @@ START_TEST(test_nonceg_creation) ng = tkm_nonceg_create(); fail_if(ng == NULL, "Error creating tkm nonce generator"); + fail_if(ng->get_id(ng) == 0, "Invalid context id (0)"); ng->nonce_gen.destroy(&ng->nonce_gen); } -- cgit v1.2.3 From 3242a178b3c9cfcf2abea5d87b247034df8bfb08 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 22 Aug 2012 10:17:59 +0200 Subject: Add chunk map This data structure allows to store mappings of chunks to ids. This will be used to map nonces to their corresponding nonce context ids. --- src/charon-tkm/src/tkm/tkm.c | 2 + src/charon-tkm/src/tkm/tkm.h | 6 ++ src/charon-tkm/src/tkm/tkm_chunk_map.c | 143 +++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_chunk_map.h | 67 +++++++++++++++ src/charon-tkm/tests/chunk_map_tests.c | 58 +++++++++++++ src/charon-tkm/tests/test_runner.c | 1 + src/charon-tkm/tests/test_runner.h | 1 + 7 files changed, 278 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_chunk_map.c create mode 100644 src/charon-tkm/src/tkm/tkm_chunk_map.h create mode 100644 src/charon-tkm/tests/chunk_map_tests.c (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index f78d49be5..e9862e026 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -81,6 +81,7 @@ bool tkm_init() INIT(this, .public = { .idmgr = tkm_id_manager_create(limits), + .chunk_map = tkm_chunk_map_create(), }, ); tkm = &this->public; @@ -99,6 +100,7 @@ void tkm_deinit() } private_tkm_t *this = (private_tkm_t*)tkm; this->public.idmgr->destroy(this->public.idmgr); + this->public.chunk_map->destroy(this->public.chunk_map); tkmlib_final(); free(this); diff --git a/src/charon-tkm/src/tkm/tkm.h b/src/charon-tkm/src/tkm/tkm.h index 6bb8331d4..9d559d9fc 100644 --- a/src/charon-tkm/src/tkm/tkm.h +++ b/src/charon-tkm/src/tkm/tkm.h @@ -18,6 +18,7 @@ #define TKM_H_ #include "tkm_id_manager.h" +#include "tkm_chunk_map.h" typedef struct tkm_t tkm_t; @@ -31,6 +32,11 @@ struct tkm_t { */ tkm_id_manager_t *idmgr; + /** + * Chunk-to-ID mappings. + */ + tkm_chunk_map_t *chunk_map; + }; /** diff --git a/src/charon-tkm/src/tkm/tkm_chunk_map.c b/src/charon-tkm/src/tkm/tkm_chunk_map.c new file mode 100644 index 000000000..2a1a944de --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_chunk_map.c @@ -0,0 +1,143 @@ +/* + * 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 . + * + * 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 +#include +#include +#include + +#include "tkm_chunk_map.h" + +typedef struct private_tkm_chunk_map_t private_tkm_chunk_map_t; + +/** + * Private data of tkm chunk map. + */ +struct private_tkm_chunk_map_t { + + /** + * public functions + */ + tkm_chunk_map_t public; + + /** + * Hashtable to store mappings. + */ + hashtable_t *mappings; + + /** + * rwlock for table. + */ + rwlock_t *lock; + +}; + +METHOD(tkm_chunk_map_t, insert, void, + private_tkm_chunk_map_t * const this, const chunk_t * const data, + const uint64_t id) +{ + uint64_t *value = malloc_thing(uint64_t); + *value = id; + + this->lock->write_lock(this->lock); + value = this->mappings->put(this->mappings, (void*)data, value); + this->lock->unlock(this->lock); + + if (value) + { + free(value); + } +} + +METHOD(tkm_chunk_map_t, get_id, uint64_t, + private_tkm_chunk_map_t * const this, chunk_t *data) +{ + uint64_t *value; + this->lock->read_lock(this->lock); + value = this->mappings->get(this->mappings, data); + this->lock->unlock(this->lock); + + return value == NULL ? 0 : *value; +} + +METHOD(tkm_chunk_map_t, remove_, bool, + private_tkm_chunk_map_t * const this, chunk_t *data) +{ + this->lock->write_lock(this->lock); + uint64_t *value = this->mappings->remove(this->mappings, data); + this->lock->unlock(this->lock); + + if (value) + { + free(value); + return TRUE; + } + else + { + return FALSE; + } +} + +METHOD(tkm_chunk_map_t, destroy, void, + private_tkm_chunk_map_t *this) +{ + uint64_t *value; + enumerator_t *enumerator; + + this->lock->write_lock(this->lock); + enumerator = this->mappings->create_enumerator(this->mappings); + while (enumerator->enumerate(enumerator, NULL, &value)) + { + this->mappings->remove_at(this->mappings, enumerator); + free(value); + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + this->lock->destroy(this->lock); + this->mappings->destroy(this->mappings); + free(this); +} + +/** + * Hashtable hash function. + */ +static u_int hash(chunk_t *key) +{ + return chunk_hash(*key); +} + +/* + * see header file + */ +tkm_chunk_map_t *tkm_chunk_map_create() +{ + private_tkm_chunk_map_t *this; + + INIT(this, + .public = { + .insert = _insert, + .get_id = _get_id, + .remove = _remove_, + .destroy = _destroy, + }, + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .mappings = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)chunk_equals_ptr, 32), + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_chunk_map.h b/src/charon-tkm/src/tkm/tkm_chunk_map.h new file mode 100644 index 000000000..746de7d4b --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_chunk_map.h @@ -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 . + * + * 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_CHUNK_MAP_H_ +#define TKM_CHUNK_MAP_H_ + +#include +#include + +typedef struct tkm_chunk_map_t tkm_chunk_map_t; + +/** + * The tkm chunk map handles mappings of chunks to ids. + */ +struct tkm_chunk_map_t { + + /** + * Store new mapping for given chunk and id. + * + * @param data data associated with id + * @param id id associated with data + */ + void (*insert)(tkm_chunk_map_t * const this, const chunk_t * const data, + const uint64_t id); + + /** + * Get id for given chunk. + * + * @param data data specifying the mapping + * @return id of given chunk, 0 if not found + */ + uint64_t (*get_id)(tkm_chunk_map_t * const this, chunk_t *data); + + /** + * Remove mapping for given chunk. + * + * @param data data specifiying the mapping to remove + * @return TRUE if mapping was removed, FALSE otherwise + */ + bool (*remove)(tkm_chunk_map_t * const this, chunk_t *data); + + /** + * Destroy a tkm chunk map instance. + */ + void (*destroy)(tkm_chunk_map_t *this); + +}; + +/** + * Create a tkm chunk map instance. + */ +tkm_chunk_map_t *tkm_chunk_map_create(); + +#endif /** TKM_CHUNK_MAP_H_ */ diff --git a/src/charon-tkm/tests/chunk_map_tests.c b/src/charon-tkm/tests/chunk_map_tests.c new file mode 100644 index 000000000..6deef9a80 --- /dev/null +++ b/src/charon-tkm/tests/chunk_map_tests.c @@ -0,0 +1,58 @@ +/* + * 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 . + * + * 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 + +#include "tkm_chunk_map.h" + +START_TEST(test_chunk_map_creation) +{ + tkm_chunk_map_t *map = NULL; + + map = tkm_chunk_map_create(); + fail_if(map == NULL, "Error creating chunk map"); + + map->destroy(map); +} +END_TEST + +START_TEST(test_chunk_map_handling) +{ + tkm_chunk_map_t *map = NULL; + const int ref = 35; + chunk_t data = chunk_from_thing(ref); + + map = tkm_chunk_map_create(); + fail_if(map == NULL, "Error creating chunk map"); + + map->insert(map, &data, 24); + fail_if(map->get_id(map, &data) != 24, "Id mismatch"); + + fail_unless(map->remove(map, &data), "Unable to remove mapping"); + fail_unless(!map->get_id(map, &data), "Error removing mapping"); + + map->destroy(map); +} +END_TEST + +TCase *make_chunk_map_tests(void) +{ + TCase *tc = tcase_create("Chunk map tests"); + tcase_add_test(tc, test_chunk_map_creation); + tcase_add_test(tc, test_chunk_map_handling); + + return tc; +} diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index 5c795f8d6..e1190fb63 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -28,6 +28,7 @@ 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_chunk_map_tests()); suite_add_tcase(s, make_nonceg_tests()); suite_add_tcase(s, make_diffie_hellman_tests()); diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h index 1de47d510..47ffd0c56 100644 --- a/src/charon-tkm/tests/test_runner.h +++ b/src/charon-tkm/tests/test_runner.h @@ -20,6 +20,7 @@ #include TCase *make_id_manager_tests(void); +TCase *make_chunk_map_tests(void); TCase *make_nonceg_tests(void); TCase *make_diffie_hellman_tests(void); -- cgit v1.2.3 From 624178fececdf6376e5ee21c330f35b0f685f8b7 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 22 Aug 2012 10:53:08 +0200 Subject: nonceg: Insert id mapping when allocating nonce --- src/charon-tkm/src/tkm/tkm_nonceg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c index 7079412cd..2723a3ee5 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.c +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -56,7 +56,12 @@ 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); + if (get_nonce(this, chunk->len, chunk->ptr)) + { + tkm->chunk_map->insert(tkm->chunk_map, chunk, this->context_id); + return TRUE; + } + return FALSE; } METHOD(nonce_gen_t, destroy, void, -- cgit v1.2.3 From ba0d7d9a76ec8dd8f53e92c8dd4b6bed794e6bf9 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 22 Aug 2012 11:05:44 +0200 Subject: keymat: Get context id of local nonce To derive IKE keys using TKM the nonce context id of the local nonce is needed. Get the id for a given chunk using the chunk map. --- src/charon-tkm/src/tkm/tkm_keymat.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 186f67b3a..644e42d74 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -17,6 +17,7 @@ #include #include +#include "tkm.h" #include "tkm_keymat.h" typedef struct private_tkm_keymat_t private_tkm_keymat_t; @@ -36,6 +37,11 @@ struct private_tkm_keymat_t { */ keymat_v2_t *proxy; + /** + * IKE_SA Role, initiator or responder + */ + bool initiator; + }; METHOD(keymat_t, get_version, ike_version_t, @@ -62,8 +68,21 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { DBG1(DBG_IKE, "deriving IKE keys"); - return this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, - nonce_r, id, rekey_function, rekey_skd); + chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r; + const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); + if (!nc_id) + { + DBG1(DBG_IKE, "unable to acquire context id for nonce"); + return FALSE; + } + + if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, + nonce_r, id, rekey_function, rekey_skd)) + { + tkm->chunk_map->remove(tkm->chunk_map, nonce); + return TRUE; + } + return FALSE; } METHOD(tkm_keymat_t, derive_child_keys, bool, @@ -136,6 +155,7 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, }, + .initiator = initiator, .proxy = keymat_v2_create(initiator), ); -- cgit v1.2.3 From 528fc21ffe01f4b7a0fcc277aeb5af3f993dbed3 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 22 Aug 2012 11:17:14 +0200 Subject: Add context id getter to TKM DH implementation --- src/charon-tkm/src/tkm/tkm_diffie_hellman.c | 7 +++++++ src/charon-tkm/src/tkm/tkm_diffie_hellman.h | 9 +++++++++ src/charon-tkm/tests/diffie_hellman_tests.c | 1 + 3 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c index 21378da5a..9a38c1637 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c @@ -103,6 +103,12 @@ METHOD(diffie_hellman_t, destroy, void, free(this); } +METHOD(tkm_diffie_hellman_t, get_id, dh_id_type, + private_tkm_diffie_hellman_t *this) +{ + return this->context_id; +} + /* * Described in header. */ @@ -119,6 +125,7 @@ tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group) .get_dh_group = _get_dh_group, .destroy = _destroy, }, + .get_id = _get_id, }, .group = group, .context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_DH), diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.h b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h index 25d196764..0f457931a 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.h +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h @@ -20,6 +20,7 @@ typedef struct tkm_diffie_hellman_t tkm_diffie_hellman_t; #include +#include /** * diffie_hellman_t implementation using the trusted key manager. @@ -30,6 +31,14 @@ struct tkm_diffie_hellman_t { * Implements diffie_hellman_t interface. */ diffie_hellman_t dh; + + /** + * Get Diffie-Hellman context id. + * + * @return id of this DH context. + */ + dh_id_type (*get_id)(tkm_diffie_hellman_t * const this); + }; /** diff --git a/src/charon-tkm/tests/diffie_hellman_tests.c b/src/charon-tkm/tests/diffie_hellman_tests.c index c2e905e76..ffe99614d 100644 --- a/src/charon-tkm/tests/diffie_hellman_tests.c +++ b/src/charon-tkm/tests/diffie_hellman_tests.c @@ -27,6 +27,7 @@ START_TEST(test_dh_creation) dh = tkm_diffie_hellman_create(MODP_4096_BIT); fail_if(!dh, "MODP_4096 not created"); + fail_if(!dh->get_id(dh), "Invalid context id (0)"); dh->dh.destroy(&dh->dh); } -- cgit v1.2.3 From d61cea752472a211166c88f1559c3677ae2ddcc0 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 22 Aug 2012 11:27:30 +0200 Subject: keymat: Log nonce and DH context ids --- src/charon-tkm/src/tkm/tkm_keymat.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 644e42d74..e3fcfa0aa 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -18,6 +18,7 @@ #include #include "tkm.h" +#include "tkm_diffie_hellman.h" #include "tkm_keymat.h" typedef struct private_tkm_keymat_t private_tkm_keymat_t; @@ -67,8 +68,9 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { - DBG1(DBG_IKE, "deriving IKE keys"); + tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh; chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r; + const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); if (!nc_id) { @@ -76,6 +78,8 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return FALSE; } + DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu)", nc_id, + tkm_dh->get_id(tkm_dh)); if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, nonce_r, id, rekey_function, rekey_skd)) { -- cgit v1.2.3 From 53232d58834efe53fda4b4fd80fc7c5440592c2d Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 24 Aug 2012 12:16:17 +0200 Subject: Implement sequence_to_chunk function This function converts a given TKM variable-length byte sequence to chunk. --- src/charon-tkm/src/tkm/tkm_diffie_hellman.c | 7 ++--- src/charon-tkm/src/tkm/tkm_utils.c | 24 +++++++++++++++ src/charon-tkm/src/tkm/tkm_utils.h | 33 +++++++++++++++++++++ src/charon-tkm/tests/test_runner.c | 1 + src/charon-tkm/tests/test_runner.h | 1 + src/charon-tkm/tests/utils_tests.c | 45 +++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/charon-tkm/src/tkm/tkm_utils.c create mode 100644 src/charon-tkm/src/tkm/tkm_utils.h create mode 100644 src/charon-tkm/tests/utils_tests.c (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c index 9a38c1637..cef53464c 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c @@ -18,6 +18,7 @@ #include #include "tkm.h" +#include "tkm_utils.h" #include "tkm_diffie_hellman.h" #include @@ -54,8 +55,7 @@ struct private_tkm_diffie_hellman_t { METHOD(diffie_hellman_t, get_my_public_value, void, private_tkm_diffie_hellman_t *this, chunk_t *value) { - *value = chunk_alloc(this->pubvalue.size); - memcpy(value->ptr, &this->pubvalue.data, value->len); + sequence_to_chunk(this->pubvalue.data, this->pubvalue.size, value); } METHOD(diffie_hellman_t, get_shared_secret, status_t, @@ -67,8 +67,7 @@ METHOD(diffie_hellman_t, get_shared_secret, status_t, return FAILED; } - *secret = chunk_alloc(shared_secret.size); - memcpy(secret->ptr, &shared_secret.data, secret->len); + sequence_to_chunk(&shared_secret.data[0], shared_secret.size, secret); return SUCCESS; } diff --git a/src/charon-tkm/src/tkm/tkm_utils.c b/src/charon-tkm/src/tkm/tkm_utils.c new file mode 100644 index 000000000..f520fb6f7 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_utils.c @@ -0,0 +1,24 @@ +/* + * 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 . + * + * 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_utils.h" + +void sequence_to_chunk(const byte_t * const first, const uint32_t len, + chunk_t * const chunk) +{ + *chunk = chunk_alloc(len); + memcpy(chunk->ptr, first, len); +} diff --git a/src/charon-tkm/src/tkm/tkm_utils.h b/src/charon-tkm/src/tkm/tkm_utils.h new file mode 100644 index 000000000..9343837f6 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_utils.h @@ -0,0 +1,33 @@ +/* + * 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 . + * + * 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_UTILS_H_ +#define TKM_UTILS_H_ + +#include +#include + +/** + * Convert byte sequence to chunk. + * + * @param first pointer to first byte of sequence + * @param len length of byte sequence + * @param chunk pointer to chunk struct + */ +void sequence_to_chunk(const byte_t * const first, const uint32_t len, + chunk_t * const chunk); + +#endif /** TKM_UTILS_H_ */ diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index e1190fb63..d29396c99 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -29,6 +29,7 @@ int main(void) Suite *s = suite_create("TKM tests"); suite_add_tcase(s, make_id_manager_tests()); suite_add_tcase(s, make_chunk_map_tests()); + suite_add_tcase(s, make_utility_tests()); suite_add_tcase(s, make_nonceg_tests()); suite_add_tcase(s, make_diffie_hellman_tests()); diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h index 47ffd0c56..c3dee9820 100644 --- a/src/charon-tkm/tests/test_runner.h +++ b/src/charon-tkm/tests/test_runner.h @@ -21,6 +21,7 @@ TCase *make_id_manager_tests(void); TCase *make_chunk_map_tests(void); +TCase *make_utility_tests(void); TCase *make_nonceg_tests(void); TCase *make_diffie_hellman_tests(void); diff --git a/src/charon-tkm/tests/utils_tests.c b/src/charon-tkm/tests/utils_tests.c new file mode 100644 index 000000000..510ebd0b7 --- /dev/null +++ b/src/charon-tkm/tests/utils_tests.c @@ -0,0 +1,45 @@ +/* + * 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 . + * + * 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 +#include + +#include "tkm_utils.h" + +START_TEST(test_sequence_to_chunk) +{ + key_type key = {5, {0, 1, 2, 3, 4}}; + chunk_t chunk = chunk_empty; + + sequence_to_chunk(key.data, key.size, &chunk); + fail_if(chunk.len != key.size, "Chunk size mismatch"); + + uint32_t i; + for (i = 0; i < key.size; i++) + { + fail_if(chunk.ptr[i] != i, "Data mismatch"); + } + chunk_free(&chunk); +} +END_TEST + +TCase *make_utility_tests(void) +{ + TCase *tc = tcase_create("Utility tests"); + tcase_add_test(tc, test_sequence_to_chunk); + + return tc; +} -- cgit v1.2.3 From 0327fac6b6f0c5ec127ab39de11fed0185e49fb7 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 24 Aug 2012 12:58:47 +0200 Subject: Implement chunk_to_sequence function This function converts a given chunk to a variable-length byte sequence. --- src/charon-tkm/src/tkm/tkm_utils.c | 14 ++++++++++++++ src/charon-tkm/src/tkm/tkm_utils.h | 8 ++++++++ src/charon-tkm/tests/utils_tests.c | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_utils.c b/src/charon-tkm/src/tkm/tkm_utils.c index f520fb6f7..e60db5906 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.c +++ b/src/charon-tkm/src/tkm/tkm_utils.c @@ -16,9 +16,23 @@ #include "tkm_utils.h" +/* Generic variable-length sequence */ +struct sequence_type { + uint32_t size; + byte_t data[]; +}; +typedef struct sequence_type sequence_type; + void sequence_to_chunk(const byte_t * const first, const uint32_t len, chunk_t * const chunk) { *chunk = chunk_alloc(len); memcpy(chunk->ptr, first, len); } + +void chunk_to_sequence(const chunk_t * const chunk, void *sequence) +{ + sequence_type *seq = sequence; + seq->size = chunk->len; + memcpy(seq->data, chunk->ptr, seq->size); +} diff --git a/src/charon-tkm/src/tkm/tkm_utils.h b/src/charon-tkm/src/tkm/tkm_utils.h index 9343837f6..c78ffd549 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.h +++ b/src/charon-tkm/src/tkm/tkm_utils.h @@ -30,4 +30,12 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, chunk_t * const chunk); +/** + * Convert chunk to variable-length byte sequence. + * + * @param chunk pointer to chunk struct + * @param sequence pointer to variable-length sequence + */ +void chunk_to_sequence(const chunk_t * const chunk, void *sequence); + #endif /** TKM_UTILS_H_ */ diff --git a/src/charon-tkm/tests/utils_tests.c b/src/charon-tkm/tests/utils_tests.c index 510ebd0b7..acc93ecf9 100644 --- a/src/charon-tkm/tests/utils_tests.c +++ b/src/charon-tkm/tests/utils_tests.c @@ -36,10 +36,28 @@ START_TEST(test_sequence_to_chunk) } END_TEST +START_TEST(test_chunk_to_sequence) +{ + chunk_t chunk = chunk_from_thing("ABCDEFGH"); + key_type key; + + chunk_to_sequence(&chunk, &key); + fail_if(key.size != chunk.len, "Seq size mismatch"); + + uint32_t i; + for (i = 0; i < key.size - 1; i++) + { + fail_if(key.data[i] != 65 + i, "Data mismatch (1)"); + } + fail_if(key.data[key.size - 1] != 0, "Data mismatch (2)"); +} +END_TEST + TCase *make_utility_tests(void) { TCase *tc = tcase_create("Utility tests"); tcase_add_test(tc, test_sequence_to_chunk); + tcase_add_test(tc, test_chunk_to_sequence); return tc; } -- cgit v1.2.3 From fc828aaac64a9681ad5351e4db959c44047b3ab0 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 24 Aug 2012 16:17:27 +0200 Subject: keymat: Call TKM Isa_Create procedure --- src/charon-tkm/src/tkm/tkm_keymat.c | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index e3fcfa0aa..6c39782c4 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -16,8 +16,11 @@ #include #include +#include +#include #include "tkm.h" +#include "tkm_utils.h" #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" @@ -68,9 +71,7 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { - tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh; chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r; - const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); if (!nc_id) { @@ -78,12 +79,46 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return FALSE; } - DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu)", nc_id, - tkm_dh->get_id(tkm_dh)); + tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh; + const dh_id_type dh_id = tkm_dh->get_id(tkm_dh); + + nonce_type nonce_rem; + u_int64_t spi_loc, spi_rem; + + if (this->initiator) + { + chunk_to_sequence(&nonce_r, &nonce_rem); + spi_loc = id->get_initiator_spi(id); + spi_rem = id->get_responder_spi(id); + } + else + { + chunk_to_sequence(&nonce_i, &nonce_rem); + spi_loc = id->get_responder_spi(id); + spi_rem = id->get_initiator_spi(id); + } + + key_type sk_ai, sk_ar, sk_ei, sk_er; + DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " + "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); + /* Fake some data for now */ + if (ike_isa_create(1, 1, 1, dh_id, nc_id, nonce_rem, 1, spi_loc, spi_rem, + &sk_ai, &sk_ar, &sk_ei, &sk_er) != TKM_OK) + { + DBG1(DBG_IKE, "key derivation failed"); + return FALSE; + } + if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, nonce_r, id, rekey_function, rekey_skd)) { tkm->chunk_map->remove(tkm->chunk_map, nonce); + if (ike_nc_reset(nc_id) != TKM_OK) + { + DBG1(DBG_IKE, "failed to reset nonce context %llu", nc_id); + } + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id); + return TRUE; } return FALSE; -- cgit v1.2.3 From 4c38878db529442d4a3b86f716687a365157d7f7 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 29 Aug 2012 09:41:02 +0200 Subject: keymat: Extract enc,inc algorithms from proposal Extract encryption and integrity algorithms from proposal and check them before deriving IKE keys. --- src/charon-tkm/src/tkm/tkm_keymat.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 6c39782c4..43c180b8a 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -71,6 +71,31 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { + /* Check encryption and integrity algorithms */ + u_int16_t enc_alg, int_alg, key_size; + if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &key_size)) + { + DBG1(DBG_IKE, "no %N selected", transform_type_names, + ENCRYPTION_ALGORITHM); + return FALSE; + } + if (encryption_algorithm_is_aead(enc_alg)) + { + DBG1(DBG_IKE, "AEAD algorithm %N not supported", + encryption_algorithm_names, enc_alg); + return FALSE; + } + if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, NULL)) + { + DBG1(DBG_IKE, "no %N selected", transform_type_names, + INTEGRITY_ALGORITHM); + return FALSE; + } + DBG2(DBG_IKE, "using %N for encryption, %N for integrity", + encryption_algorithm_names, enc_alg, + integrity_algorithm_names, int_alg); + + /* Acquire nonce context id */ chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r; const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); if (!nc_id) @@ -79,6 +104,7 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return FALSE; } + /* Get DH context id */ tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh; const dh_id_type dh_id = tkm_dh->get_id(tkm_dh); -- cgit v1.2.3 From 3290b9995c2de88979bb6a4dd1fc8b743f2080eb Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 29 Aug 2012 09:44:17 +0200 Subject: keymat: Create inbound and outbound AEAD transforms Create and initialize AEAD transforms with keys derived by the TKM. Return these transforms in the get_aead function. IKE keys used by charon are derived by TKM now. --- src/charon-tkm/src/tkm/tkm_keymat.c | 88 +++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 43c180b8a..ab78994ec 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -42,10 +42,20 @@ struct private_tkm_keymat_t { keymat_v2_t *proxy; /** - * IKE_SA Role, initiator or responder + * IKE_SA Role, initiator or responder. */ bool initiator; + /** + * Inbound AEAD. + */ + aead_t *aead_in; + + /** + * Outbound AEAD. + */ + aead_t *aead_out; + }; METHOD(keymat_t, get_version, ike_version_t, @@ -135,6 +145,76 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return FALSE; } + /* Initialize AEAD with crypters and signers */ + signer_t * const signer_i = lib->crypto->create_signer(lib->crypto, int_alg); + signer_t * const signer_r = lib->crypto->create_signer(lib->crypto, int_alg); + if (signer_i == NULL || signer_r == NULL) + { + DBG1(DBG_IKE, "%N %N not supported!", + transform_type_names, INTEGRITY_ALGORITHM, + integrity_algorithm_names, int_alg); + return FALSE; + } + crypter_t * const crypter_i = lib->crypto->create_crypter(lib->crypto, + enc_alg, key_size / 8); + crypter_t * const crypter_r = lib->crypto->create_crypter(lib->crypto, + enc_alg, key_size / 8); + if (crypter_i == NULL || crypter_r == NULL) + { + signer_i->destroy(signer_i); + signer_r->destroy(signer_r); + DBG1(DBG_IKE, "%N %N (key size %d) not supported!", + transform_type_names, ENCRYPTION_ALGORITHM, + encryption_algorithm_names, enc_alg, key_size); + return FALSE; + } + + chunk_t key; + sequence_to_chunk(sk_ai.data, sk_ai.size, &key); + DBG4(DBG_IKE, "Sk_ai %B", &key); + if (!signer_i->set_key(signer_i, key)) + { + return FALSE; + } + chunk_clear(&key); + + sequence_to_chunk(sk_ar.data, sk_ar.size, &key); + DBG4(DBG_IKE, "Sk_ar %B", &key); + if (!signer_r->set_key(signer_r, key)) + { + return FALSE; + } + chunk_clear(&key); + + sequence_to_chunk(sk_ei.data, sk_ei.size, &key); + DBG4(DBG_IKE, "Sk_ei %B", &key); + if (!crypter_i->set_key(crypter_i, key)) + { + return FALSE; + } + chunk_clear(&key); + + sequence_to_chunk(sk_er.data, sk_er.size, &key); + DBG4(DBG_IKE, "Sk_er %B", &key); + if (!crypter_r->set_key(crypter_r, key)) + { + return FALSE; + } + chunk_clear(&key); + + if (this->initiator) + { + this->aead_in = aead_create(crypter_r, signer_r); + this->aead_out = aead_create(crypter_i, signer_i); + } + else + { + this->aead_in = aead_create(crypter_i, signer_i); + this->aead_out = aead_create(crypter_r, signer_r); + } + + /* TODO: Add failure handler (see keymat_v2.c) */ + if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, nonce_r, id, rekey_function, rekey_skd)) { @@ -163,8 +243,7 @@ METHOD(tkm_keymat_t, derive_child_keys, bool, METHOD(keymat_t, get_aead, aead_t*, private_tkm_keymat_t *this, bool in) { - DBG1(DBG_IKE, "returning aead transform"); - return this->proxy->keymat.get_aead(&this->proxy->keymat, in); + return in ? this->aead_in : this->aead_out; } METHOD(tkm_keymat_t, get_auth_octets, bool, @@ -195,6 +274,9 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, METHOD(keymat_t, destroy, void, private_tkm_keymat_t *this) { + DESTROY_IF(this->aead_in); + DESTROY_IF(this->aead_out); + this->proxy->keymat.destroy(&this->proxy->keymat); free(this); } -- cgit v1.2.3 From 4be8471fab1bccd078d7ee2fccba77e97f76b52b Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 29 Aug 2012 09:48:14 +0200 Subject: Add keymat IKE key derivation test case --- src/charon-tkm/tests/keymat_tests.c | 103 ++++++++++++++++++++++++++++++++++++ src/charon-tkm/tests/test_runner.c | 1 + src/charon-tkm/tests/test_runner.h | 1 + 3 files changed, 105 insertions(+) create mode 100644 src/charon-tkm/tests/keymat_tests.c (limited to 'src') diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c new file mode 100644 index 000000000..fbaed24e4 --- /dev/null +++ b/src/charon-tkm/tests/keymat_tests.c @@ -0,0 +1,103 @@ +/* + * 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 . + * + * 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 +#include +#include +#include +#include +#include + +#include "tkm.h" +#include "tkm_nonceg.h" +#include "tkm_diffie_hellman.h" +#include "tkm_keymat.h" + +START_TEST(test_derive_ike_keys) +{ + fail_if(!library_init(NULL), "Unable to init library"); + fail_if(!libhydra_init("tkm-tests"), "Unable to init libhydra"); + fail_if(!libcharon_init("tkm-tests"), "Unable to init libcharon"); + + /* Register TKM specific plugins */ + static plugin_feature_t features[] = { + PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), + PLUGIN_PROVIDE(NONCE_GEN), + PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), + PLUGIN_PROVIDE(DH, MODP_3072_BIT), + PLUGIN_PROVIDE(DH, MODP_4096_BIT), + }; + lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, + countof(features), TRUE); + + fail_if(!charon->initialize(charon, PLUGINS), "Unable to init charon"); + + proposal_t *proposal = proposal_create_from_string(PROTO_IKE, + "aes256-sha512-modp4096"); + fail_if(!proposal, "Unable to create proposal"); + ike_sa_id_t *ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, + 123912312312, 32312313122, TRUE); + fail_if(!ike_sa_id, "Unable to create IKE SA ID"); + + tkm_keymat_t *keymat = tkm_keymat_create(TRUE); + fail_if(!keymat, "Unable to create keymat"); + + chunk_t nonce; + tkm_nonceg_t *ng = tkm_nonceg_create(); + fail_if(!ng, "Unable to create nonce generator"); + fail_unless(ng->nonce_gen.allocate_nonce(&ng->nonce_gen, 32, &nonce), + "Unable to allocate nonce"); + ng->nonce_gen.destroy(&ng->nonce_gen); + + tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT); + fail_if(!dh, "Unable to create DH"); + + /* Use the same pubvalue for both sides */ + chunk_t pubvalue; + dh->dh.get_my_public_value(&dh->dh, &pubvalue); + dh->dh.set_other_public_value(&dh->dh, pubvalue); + + fail_unless(keymat->derive_ike_keys(keymat, proposal, &dh->dh, nonce, nonce, + ike_sa_id, PRF_UNDEFINED, chunk_empty), "Key derivation failed"); + chunk_free(&nonce); + + aead_t * const aead = keymat->keymat.get_aead(&keymat->keymat, TRUE); + fail_if(!aead, "AEAD is NULL"); + + fail_if(aead->get_key_size(aead) != 96, "Key size mismatch %d", + aead->get_key_size(aead)); + fail_if(aead->get_block_size(aead) != 16, "Block size mismatch %d", + aead->get_block_size(aead)); + + proposal->destroy(proposal); + dh->dh.destroy(&dh->dh); + ike_sa_id->destroy(ike_sa_id); + keymat->keymat.destroy(&keymat->keymat); + chunk_free(&pubvalue); + + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); +} +END_TEST + +TCase *make_keymat_tests(void) +{ + TCase *tc = tcase_create("Keymat tests"); + tcase_add_test(tc, test_derive_ike_keys); + + return tc; +} diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index d29396c99..6ab990d92 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -32,6 +32,7 @@ int main(void) suite_add_tcase(s, make_utility_tests()); suite_add_tcase(s, make_nonceg_tests()); suite_add_tcase(s, make_diffie_hellman_tests()); + suite_add_tcase(s, make_keymat_tests()); SRunner *sr = srunner_create(s); diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h index c3dee9820..c8cc0c0db 100644 --- a/src/charon-tkm/tests/test_runner.h +++ b/src/charon-tkm/tests/test_runner.h @@ -24,5 +24,6 @@ TCase *make_chunk_map_tests(void); TCase *make_utility_tests(void); TCase *make_nonceg_tests(void); TCase *make_diffie_hellman_tests(void); +TCase *make_keymat_tests(void); #endif /** TEST_RUNNER_H_ */ -- cgit v1.2.3 From e285544be2a8c561b3d84bf43523c761526879c6 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 29 Aug 2012 10:38:47 +0200 Subject: Factor out AEAD transform creation Introduce static aead_create_from_keys function to initialize AEAD transforms from key chunks. --- src/charon-tkm/src/tkm/tkm_keymat.c | 153 ++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index ab78994ec..36067eae8 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -58,6 +58,84 @@ struct private_tkm_keymat_t { }; +/** + * Create AEAD transforms from given key chunks. + * + * @param in inbound AEAD transform to allocate, NULL if failed + * @param out outbound AEAD transform to allocate, NULL if failed + * @param sk_ai SK_ai key chunk + * @param sk_ar SK_ar key chunk + * @param sk_ei SK_ei key chunk + * @param sk_er SK_er key chunk + * @param enc_alg encryption algorithm to use + * @param int_alg integrity algorithm to use + * @param key_size encryption key size in bytes + * @param initiator TRUE if initiator + */ +static void aead_create_from_keys(aead_t **in, aead_t **out, + const chunk_t * const sk_ai, const chunk_t * const sk_ar, + const chunk_t * const sk_ei, const chunk_t * const sk_er, + const u_int16_t enc_alg, const u_int16_t int_alg, + const u_int16_t key_size, bool initiator) +{ + *in = *out = NULL; + + signer_t * const signer_i = lib->crypto->create_signer(lib->crypto, int_alg); + signer_t * const signer_r = lib->crypto->create_signer(lib->crypto, int_alg); + if (signer_i == NULL || signer_r == NULL) + { + DBG1(DBG_IKE, "%N %N not supported!", + transform_type_names, INTEGRITY_ALGORITHM, + integrity_algorithm_names, int_alg); + return; + } + crypter_t * const crypter_i = lib->crypto->create_crypter(lib->crypto, + enc_alg, key_size); + crypter_t * const crypter_r = lib->crypto->create_crypter(lib->crypto, + enc_alg, key_size); + if (crypter_i == NULL || crypter_r == NULL) + { + signer_i->destroy(signer_i); + signer_r->destroy(signer_r); + DBG1(DBG_IKE, "%N %N (key size %d) not supported!", + transform_type_names, ENCRYPTION_ALGORITHM, + encryption_algorithm_names, enc_alg, key_size); + return; + } + + DBG4(DBG_IKE, "Sk_ai %B", sk_ai); + if (!signer_i->set_key(signer_i, *sk_ai)) + { + return; + } + DBG4(DBG_IKE, "Sk_ar %B", sk_ar); + if (!signer_r->set_key(signer_r, *sk_ar)) + { + return; + } + DBG4(DBG_IKE, "Sk_ei %B", sk_ei); + if (!crypter_i->set_key(crypter_i, *sk_ei)) + { + return; + } + DBG4(DBG_IKE, "Sk_er %B", sk_er); + if (!crypter_r->set_key(crypter_r, *sk_er)) + { + return; + } + + if (initiator) + { + *in = aead_create(crypter_r, signer_r); + *out = aead_create(crypter_i, signer_i); + } + else + { + *in = aead_create(crypter_i, signer_i); + *out = aead_create(crypter_r, signer_r); + } +} + METHOD(keymat_t, get_version, ike_version_t, private_tkm_keymat_t *this) { @@ -145,73 +223,26 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return FALSE; } - /* Initialize AEAD with crypters and signers */ - signer_t * const signer_i = lib->crypto->create_signer(lib->crypto, int_alg); - signer_t * const signer_r = lib->crypto->create_signer(lib->crypto, int_alg); - if (signer_i == NULL || signer_r == NULL) - { - DBG1(DBG_IKE, "%N %N not supported!", - transform_type_names, INTEGRITY_ALGORITHM, - integrity_algorithm_names, int_alg); - return FALSE; - } - crypter_t * const crypter_i = lib->crypto->create_crypter(lib->crypto, - enc_alg, key_size / 8); - crypter_t * const crypter_r = lib->crypto->create_crypter(lib->crypto, - enc_alg, key_size / 8); - if (crypter_i == NULL || crypter_r == NULL) - { - signer_i->destroy(signer_i); - signer_r->destroy(signer_r); - DBG1(DBG_IKE, "%N %N (key size %d) not supported!", - transform_type_names, ENCRYPTION_ALGORITHM, - encryption_algorithm_names, enc_alg, key_size); - return FALSE; - } - - chunk_t key; - sequence_to_chunk(sk_ai.data, sk_ai.size, &key); - DBG4(DBG_IKE, "Sk_ai %B", &key); - if (!signer_i->set_key(signer_i, key)) - { - return FALSE; - } - chunk_clear(&key); + chunk_t c_ai, c_ar, c_ei, c_er; + sequence_to_chunk(sk_ai.data, sk_ai.size, &c_ai); + sequence_to_chunk(sk_ar.data, sk_ar.size, &c_ar); + sequence_to_chunk(sk_ei.data, sk_ei.size, &c_ei); + sequence_to_chunk(sk_er.data, sk_er.size, &c_er); - sequence_to_chunk(sk_ar.data, sk_ar.size, &key); - DBG4(DBG_IKE, "Sk_ar %B", &key); - if (!signer_r->set_key(signer_r, key)) - { - return FALSE; - } - chunk_clear(&key); + aead_create_from_keys(&this->aead_in, &this->aead_out, + &c_ai, &c_ar, &c_ei, &c_er, + enc_alg, int_alg, key_size / 8, this->initiator); - sequence_to_chunk(sk_ei.data, sk_ei.size, &key); - DBG4(DBG_IKE, "Sk_ei %B", &key); - if (!crypter_i->set_key(crypter_i, key)) - { - return FALSE; - } - chunk_clear(&key); + chunk_clear(&c_ai); + chunk_clear(&c_ar); + chunk_clear(&c_ei); + chunk_clear(&c_er); - sequence_to_chunk(sk_er.data, sk_er.size, &key); - DBG4(DBG_IKE, "Sk_er %B", &key); - if (!crypter_r->set_key(crypter_r, key)) + if (!this->aead_in || !this->aead_out) { + DBG1(DBG_IKE, "could not initialize AEAD transforms"); return FALSE; } - chunk_clear(&key); - - if (this->initiator) - { - this->aead_in = aead_create(crypter_r, signer_r); - this->aead_out = aead_create(crypter_i, signer_i); - } - else - { - this->aead_in = aead_create(crypter_i, signer_i); - this->aead_out = aead_create(crypter_r, signer_r); - } /* TODO: Add failure handler (see keymat_v2.c) */ -- cgit v1.2.3 From 51fdbd042901635280f98d4ee96231b2890f7feb Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 29 Aug 2012 18:32:28 +0200 Subject: keymat: Call ike_isa_sign_psk in get_psk_sig Get PSK signed AUTH octets from TKM in initiator case. --- src/charon-tkm/src/tkm/tkm_keymat.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 36067eae8..0c71967e3 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -298,8 +298,33 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) { DBG1(DBG_IKE, "returning PSK signature"); - return this->proxy->get_psk_sig(this->proxy, verify, ike_sa_init, nonce, + if (!verify) + { + signature_type signature; + init_message_type msg; + chunk_to_sequence(&ike_sa_init, &msg); + + chunk_t idx_chunk, chunk = chunk_alloca(4); + chunk.ptr[0] = id->get_type(id); + memcpy(chunk.ptr + 1, reserved, 3); + idx_chunk = chunk_cata("cc", chunk, id->get_encoding(id)); + idx_type idx; + chunk_to_sequence(&idx_chunk, &idx); + + if (ike_isa_sign_psk(1, msg, idx, &signature) != TKM_OK) + { + DBG1(DBG_IKE, "get local PSK signature failed"); + return FALSE; + } + + sequence_to_chunk(&signature.data[0], signature.size, sig); + return TRUE; + } + else + { + return this->proxy->get_psk_sig(this->proxy, verify, ike_sa_init, nonce, secret, id, reserved, sig); + } } METHOD(keymat_t, destroy, void, -- cgit v1.2.3 From e7a497c30761a7e949ea928401a785eecd6db31b Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 30 Aug 2012 11:25:14 +0200 Subject: keymat: Check for aes256-sha512 in derive_ike_keys Return FALSE if peers try to use other algorithm combinations. --- src/charon-tkm/src/tkm/tkm_keymat.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 0c71967e3..43e0c1f02 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -179,6 +179,14 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, INTEGRITY_ALGORITHM); return FALSE; } + if (!(enc_alg == ENCR_AES_CBC && key_size == 256 && + int_alg == AUTH_HMAC_SHA2_512_256)) + { + DBG1(DBG_IKE, "the TKM only supports aes256-sha512 at the moment, please" + " update your configuration"); + return FALSE; + } + DBG2(DBG_IKE, "using %N for encryption, %N for integrity", encryption_algorithm_names, enc_alg, integrity_algorithm_names, int_alg); -- cgit v1.2.3 From fa22fc2419258fafd47aece838ea21d0fe26ed0b Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 30 Aug 2012 13:57:58 +0200 Subject: Use remote PSK signature computed by TKM --- src/charon-tkm/src/tkm/tkm_keymat.c | 44 ++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 43e0c1f02..3b1fd1cd2 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -305,34 +305,28 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) { - DBG1(DBG_IKE, "returning PSK signature"); - if (!verify) - { - signature_type signature; - init_message_type msg; - chunk_to_sequence(&ike_sa_init, &msg); - - chunk_t idx_chunk, chunk = chunk_alloca(4); - chunk.ptr[0] = id->get_type(id); - memcpy(chunk.ptr + 1, reserved, 3); - idx_chunk = chunk_cata("cc", chunk, id->get_encoding(id)); - idx_type idx; - chunk_to_sequence(&idx_chunk, &idx); - - if (ike_isa_sign_psk(1, msg, idx, &signature) != TKM_OK) - { - DBG1(DBG_IKE, "get local PSK signature failed"); - return FALSE; - } + DBG1(DBG_IKE, "returning %s PSK signature", verify ? "remote" : "local"); - sequence_to_chunk(&signature.data[0], signature.size, sig); - return TRUE; - } - else + signature_type signature; + init_message_type msg; + chunk_to_sequence(&ike_sa_init, &msg); + + chunk_t idx_chunk, chunk = chunk_alloca(4); + chunk.ptr[0] = id->get_type(id); + memcpy(chunk.ptr + 1, reserved, 3); + idx_chunk = chunk_cata("cc", chunk, id->get_encoding(id)); + idx_type idx; + chunk_to_sequence(&idx_chunk, &idx); + + if (ike_isa_sign_psk(1, msg, idx, verify == TRUE, &signature) != TKM_OK) { - return this->proxy->get_psk_sig(this->proxy, verify, ike_sa_init, nonce, - secret, id, reserved, sig); + DBG1(DBG_IKE, "get %s PSK signature failed", verify ? + "remote" : "local"); + return FALSE; } + + sequence_to_chunk(&signature.data[0], signature.size, sig); + return TRUE; } METHOD(keymat_t, destroy, void, -- cgit v1.2.3 From 7fb3e5ed104e12822fa5a62fcd3db27b52bc1f67 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 30 Aug 2012 14:36:06 +0200 Subject: Add TKM_CTX_ISA (IKE SA context) --- src/charon-tkm/src/tkm/tkm.c | 3 +-- src/charon-tkm/src/tkm/tkm_id_manager.c | 7 ++++--- src/charon-tkm/src/tkm/tkm_id_manager.h | 2 ++ src/charon-tkm/tests/id_manager_tests.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index e9862e026..31e01c6b9 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -75,8 +75,7 @@ bool tkm_init() return FALSE; } - /* only nonce and DH context limits are currently needed */ - const tkm_limits_t limits = {nc, dh}; + const tkm_limits_t limits = {nc, dh, isa}; INIT(this, .public = { diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 8cafa4193..486a91225 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -22,10 +22,11 @@ #define TKM_LIMIT 100 -ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH, +ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ISA, "NONCE_CONTEXT", - "DH_CONTEXT"); -ENUM_END(tkm_context_kind_names, TKM_CTX_DH); + "DH_CONTEXT", + "ISA_CONTEXT"); +ENUM_END(tkm_context_kind_names, TKM_CTX_ISA); typedef struct private_tkm_id_manager_t private_tkm_id_manager_t; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 9fbdb2d72..8a9b6d498 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -30,6 +30,8 @@ enum tkm_context_kind_t { TKM_CTX_NONCE, /** Diffie-Hellman context */ TKM_CTX_DH, + /** IKE SA context */ + TKM_CTX_ISA, /** helper to determine the number of elements in this enum */ TKM_CTX_MAX, diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index 86e80aee0..59c82fe71 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -18,7 +18,7 @@ #include "tkm_id_manager.h" -static const tkm_limits_t limits = {125, 100}; +static const tkm_limits_t limits = {125, 100, 30}; START_TEST(test_id_mgr_creation) { -- cgit v1.2.3 From bf1034a7764d10dece4744750d3ab42706131ec3 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 30 Aug 2012 14:42:19 +0200 Subject: keymat: Acquire ISA context ID on initialization --- src/charon-tkm/src/tkm/tkm_keymat.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 3b1fd1cd2..50d93fc64 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -56,6 +56,11 @@ struct private_tkm_keymat_t { */ aead_t *aead_out; + /** + * ISA context id. + */ + isa_id_type isa_ctx_id; + }; /** @@ -224,7 +229,8 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); /* Fake some data for now */ - if (ike_isa_create(1, 1, 1, dh_id, nc_id, nonce_rem, 1, spi_loc, spi_rem, + if (ike_isa_create(this->isa_ctx_id, 1, 1, dh_id, nc_id, nonce_rem, 1, + spi_loc, spi_rem, &sk_ai, &sk_ar, &sk_ei, &sk_er) != TKM_OK) { DBG1(DBG_IKE, "key derivation failed"); @@ -318,7 +324,8 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, idx_type idx; chunk_to_sequence(&idx_chunk, &idx); - if (ike_isa_sign_psk(1, msg, idx, verify == TRUE, &signature) != TKM_OK) + if (ike_isa_sign_psk(this->isa_ctx_id, msg, idx, verify == TRUE, &signature) + != TKM_OK) { DBG1(DBG_IKE, "get %s PSK signature failed", verify ? "remote" : "local"); @@ -332,6 +339,12 @@ METHOD(tkm_keymat_t, get_psk_sig, bool, METHOD(keymat_t, destroy, void, private_tkm_keymat_t *this) { + if (ike_isa_reset(this->isa_ctx_id) != TKM_OK) + { + DBG1(DBG_IKE, "failed to reset ISA context %d", this->isa_ctx_id); + } + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ISA, this->isa_ctx_id); + DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); this->proxy->keymat.destroy(&this->proxy->keymat); @@ -361,8 +374,15 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_psk_sig = _get_psk_sig, }, .initiator = initiator, + .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), .proxy = keymat_v2_create(initiator), ); + if (!this->isa_ctx_id) + { + free(this); + return NULL; + } + return &this->public; } -- cgit v1.2.3 From c755645032c9c3586f8bac9644863bec1835eb57 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 30 Aug 2012 15:07:21 +0200 Subject: Add TKM_CTX_AE (Authenticated Endpoint context) --- src/charon-tkm/src/tkm/tkm.c | 2 +- src/charon-tkm/src/tkm/tkm_id_manager.c | 7 ++++--- src/charon-tkm/src/tkm/tkm_id_manager.h | 2 ++ src/charon-tkm/tests/id_manager_tests.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 31e01c6b9..f2ffd2838 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -75,7 +75,7 @@ bool tkm_init() return FALSE; } - const tkm_limits_t limits = {nc, dh, isa}; + const tkm_limits_t limits = {nc, dh, isa, ae}; INIT(this, .public = { diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 486a91225..6120c32a7 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -22,11 +22,12 @@ #define TKM_LIMIT 100 -ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ISA, +ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_AE, "NONCE_CONTEXT", "DH_CONTEXT", - "ISA_CONTEXT"); -ENUM_END(tkm_context_kind_names, TKM_CTX_ISA); + "ISA_CONTEXT", + "AE_CONTEXT"); +ENUM_END(tkm_context_kind_names, TKM_CTX_AE); typedef struct private_tkm_id_manager_t private_tkm_id_manager_t; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 8a9b6d498..17ca01720 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -32,6 +32,8 @@ enum tkm_context_kind_t { TKM_CTX_DH, /** IKE SA context */ TKM_CTX_ISA, + /** Authenticated Endpoint context */ + TKM_CTX_AE, /** helper to determine the number of elements in this enum */ TKM_CTX_MAX, diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index 59c82fe71..c4d53661f 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -18,7 +18,7 @@ #include "tkm_id_manager.h" -static const tkm_limits_t limits = {125, 100, 30}; +static const tkm_limits_t limits = {125, 100, 30, 200}; START_TEST(test_id_mgr_creation) { -- cgit v1.2.3 From cdd4d73ff5e012814bdc896eefb1977c2b0372b7 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 31 Aug 2012 10:13:55 +0200 Subject: keymat: Acquire AE context ID on initialization --- src/charon-tkm/src/tkm/tkm_keymat.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 50d93fc64..d055c3847 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -61,6 +61,11 @@ struct private_tkm_keymat_t { */ isa_id_type isa_ctx_id; + /** + * AE context id. + */ + ae_id_type ae_ctx_id; + }; /** @@ -229,8 +234,8 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); /* Fake some data for now */ - if (ike_isa_create(this->isa_ctx_id, 1, 1, dh_id, nc_id, nonce_rem, 1, - spi_loc, spi_rem, + if (ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, dh_id, nc_id, + nonce_rem, 1, spi_loc, spi_rem, &sk_ai, &sk_ar, &sk_ei, &sk_er) != TKM_OK) { DBG1(DBG_IKE, "key derivation failed"); @@ -375,10 +380,11 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) }, .initiator = initiator, .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), + .ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE), .proxy = keymat_v2_create(initiator), ); - if (!this->isa_ctx_id) + if (!this->isa_ctx_id || !this->ae_ctx_id) { free(this); return NULL; -- cgit v1.2.3 From d91acfdb5d25b5993e12f70f05f185458abcd901 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 31 Aug 2012 11:24:45 +0200 Subject: Add ISA context id getter to TKM keymat --- src/charon-tkm/src/tkm/tkm_keymat.c | 7 +++++++ src/charon-tkm/src/tkm/tkm_keymat.h | 8 ++++++++ src/charon-tkm/tests/keymat_tests.c | 1 + 3 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index d055c3847..bb085b86f 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -356,6 +356,12 @@ METHOD(keymat_t, destroy, void, free(this); } +METHOD(tkm_keymat_t, get_isa_id, isa_id_type, + private_tkm_keymat_t *this) +{ + return this->isa_ctx_id; +} + /** * See header. */ @@ -377,6 +383,7 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_skd = _get_skd, .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, + .get_isa_id = _get_isa_id, }, .initiator = initiator, .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index 2def71fb3..1fb15596a 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -106,6 +106,14 @@ struct tkm_keymat_t { bool (*get_psk_sig)(tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig); + + /** + * Get ISA context id. + * + * @return id of associated ISA context. + */ + isa_id_type (*get_isa_id)(tkm_keymat_t * const this); + }; /** diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index fbaed24e4..0fde2fb6e 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -54,6 +54,7 @@ START_TEST(test_derive_ike_keys) tkm_keymat_t *keymat = tkm_keymat_create(TRUE); fail_if(!keymat, "Unable to create keymat"); + fail_if(!keymat->get_isa_id(keymat), "Invalid ISA context id (0)"); chunk_t nonce; tkm_nonceg_t *ng = tkm_nonceg_create(); -- cgit v1.2.3 From c6c8d74026f149d456ab900445f6efbcd7d9d4bb Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 31 Aug 2012 11:11:30 +0200 Subject: Add TKM specific bus listener skeleton This listener gets informed about IKE authorization rounds and will be used to call ike_isa_auth on a given ISA. --- src/charon-tkm/src/tkm/tkm_listener.c | 77 +++++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_listener.h | 47 +++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_listener.c create mode 100644 src/charon-tkm/src/tkm/tkm_listener.h (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c new file mode 100644 index 000000000..ee8fb4925 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -0,0 +1,77 @@ +/* + * 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 . + * + * 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 +#include + +#include "tkm_listener.h" +#include "tkm_keymat.h" + +typedef struct private_tkm_listener_t private_tkm_listener_t; + +/** + * Private data of a tkm_listener_t object. + */ +struct private_tkm_listener_t { + + /** + * Public tkm_listener_t interface. + */ + tkm_listener_t public; + +}; + +METHOD(listener_t, authorize, bool, + private_tkm_listener_t *this, ike_sa_t *ike_sa, + bool final, bool *success) +{ + if (!final) + { + return TRUE; + } + + tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + const isa_id_type isa_id = keymat->get_isa_id(keymat); + DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id); + + *success = TRUE; + return TRUE; +} + +METHOD(tkm_listener_t, destroy, void, + private_tkm_listener_t *this) +{ + free(this); +} + +/** + * See header + */ +tkm_listener_t *tkm_listener_create() +{ + private_tkm_listener_t *this; + + INIT(this, + .public = { + .listener = { + .authorize = _authorize, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_listener.h b/src/charon-tkm/src/tkm/tkm_listener.h new file mode 100644 index 000000000..262d66e33 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_listener.h @@ -0,0 +1,47 @@ +/* + * 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 . + * + * 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_LISTENER_H_ +#define TKM_LISTENER_H_ + +#include + +typedef struct tkm_listener_t tkm_listener_t; + +/** + * TKM bus listener. + */ +struct tkm_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a tkm_listener_t. + */ + void (*destroy)(tkm_listener_t *this); +}; + +/** + * Create a tkm_listener instance. + * + * @return listener instance + */ +tkm_listener_t *tkm_listener_create(); + +#endif /** TKM_LISTENER_H_ */ -- cgit v1.2.3 From d0ce4116b0380dbfa3890781c6cf2e40f9ac4654 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 31 Aug 2012 11:13:39 +0200 Subject: Register TKM bus listener in charon-tkm --- src/charon-tkm/src/charon-tkm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index e102b4e0d..f2a58b21e 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -37,6 +37,12 @@ #include "tkm_nonceg.h" #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" +#include "tkm_listener.h" + +/** + * TKM bus listener for IKE authorize events. + */ +static tkm_listener_t *listener; /** * PID file, in which charon-tkm stores its process id @@ -319,6 +325,10 @@ int main(int argc, char *argv[]) goto deinit; } + /* register TKM authorization hook */ + listener = tkm_listener_create(); + charon->bus->add_listener(charon->bus, &listener->listener); + /* add handler for SEGV and ILL, * INT and TERM are handled by sigwait() in run() */ action.sa_handler = segv_handler; @@ -342,6 +352,8 @@ int main(int argc, char *argv[]) unlink_pidfile(); status = 0; + charon->bus->remove_listener(charon->bus, &listener->listener); + listener->destroy(listener); deinit: libcharon_deinit(); -- cgit v1.2.3 From 071e792a85f2128f07d2cbf1c1c9ab7531131c1f Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 6 Sep 2012 17:27:45 +0200 Subject: keymat: Add AUTH payload setter/getter functions These functions are used in the TKM specific bus listener to store/retrieve the AUTH payload chunk in the message/authorize hooks. --- src/charon-tkm/src/tkm/tkm_keymat.c | 21 +++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_keymat.h | 14 ++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index bb085b86f..b36353b5c 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -66,6 +66,11 @@ struct private_tkm_keymat_t { */ ae_id_type ae_ctx_id; + /** + * AUTH payload chunk. + */ + chunk_t auth_payload; + }; /** @@ -352,6 +357,7 @@ METHOD(keymat_t, destroy, void, DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); + chunk_free(&this->auth_payload); this->proxy->keymat.destroy(&this->proxy->keymat); free(this); } @@ -362,6 +368,18 @@ METHOD(tkm_keymat_t, get_isa_id, isa_id_type, return this->isa_ctx_id; } +METHOD(tkm_keymat_t, set_auth_payload, void, + private_tkm_keymat_t *this, const chunk_t * const payload) +{ + this->auth_payload = chunk_clone(*payload); +} + +METHOD(tkm_keymat_t, get_auth_payload, chunk_t*, + private_tkm_keymat_t *this) +{ + return &this->auth_payload; +} + /** * See header. */ @@ -384,10 +402,13 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, .get_isa_id = _get_isa_id, + .set_auth_payload = _set_auth_payload, + .get_auth_payload = _get_auth_payload, }, .initiator = initiator, .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), .ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE), + .auth_payload = chunk_empty, .proxy = keymat_v2_create(initiator), ); diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index 1fb15596a..22da32f4e 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -114,6 +114,20 @@ struct tkm_keymat_t { */ isa_id_type (*get_isa_id)(tkm_keymat_t * const this); + /** + * Set IKE AUTH payload. + * + * @param payload AUTH payload + */ + void (*set_auth_payload)(tkm_keymat_t *this, const chunk_t * const payload); + + /** + * Get IKE AUTH payload. + * + * @return AUTH payload if set, chunk_empty otherwise + */ + chunk_t* (*get_auth_payload)(tkm_keymat_t * const this); + }; /** -- cgit v1.2.3 From 9df5645623aa19959eaa7648f15caff6387f8fd0 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 31 Aug 2012 12:58:00 +0200 Subject: listener: Register message hook Use the message hook to save the AUTHENTICATION payload of an incoming IKE_AUTH message. The AUTH payload will be passed on to the TKM ike_isa_auth operation in the authorize hook. --- src/charon-tkm/src/tkm/tkm_listener.c | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index ee8fb4925..536ba78b2 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -15,6 +15,8 @@ */ #include +#include +#include #include #include "tkm_listener.h" @@ -47,10 +49,49 @@ METHOD(listener_t, authorize, bool, const isa_id_type isa_id = keymat->get_isa_id(keymat); DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id); + const chunk_t * const auth = keymat->get_auth_payload(keymat); + if (!auth->ptr) + { + DBG1(DBG_IKE, "no AUTHENTICATION data available"); + *success = FALSE; + } + + DBG1(DBG_IKE, "TKM based authentication successful" + " for ISA context %llu", isa_id); *success = TRUE; return TRUE; } +METHOD(listener_t, message, bool, + private_tkm_listener_t *this, ike_sa_t *ike_sa, + message_t *message, bool incoming, bool plain) +{ + if (!incoming || !plain || message->get_exchange_type(message) != IKE_AUTH) + { + return TRUE; + } + + tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + const isa_id_type isa_id = keymat->get_isa_id(keymat); + DBG1(DBG_IKE, "saving AUTHENTICATION payload for authorize hook" + " (ISA context %llu)", isa_id); + + auth_payload_t * const auth_payload = + (auth_payload_t*)message->get_payload(message, AUTHENTICATION); + if (auth_payload) + { + const chunk_t auth_data = auth_payload->get_data(auth_payload); + keymat->set_auth_payload(keymat, &auth_data); + } + else + { + DBG1(DBG_IKE, "unable to extract AUTHENTICATION payload, authorize will" + " fail"); + } + + return TRUE; +} + METHOD(tkm_listener_t, destroy, void, private_tkm_listener_t *this) { @@ -68,6 +109,7 @@ tkm_listener_t *tkm_listener_create() .public = { .listener = { .authorize = _authorize, + .message = _message, }, .destroy = _destroy, }, -- cgit v1.2.3 From 39727696904fafbda04fbc02ccd058b12ec2a99a Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 6 Sep 2012 18:17:26 +0200 Subject: Call ike_isa_auth_psk in listener authorize hook This exchange initiates the AUTH verification in the TKM. --- src/charon-tkm/src/tkm/tkm_listener.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 536ba78b2..557b276b8 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -18,9 +18,12 @@ #include #include #include +#include +#include #include "tkm_listener.h" #include "tkm_keymat.h" +#include "tkm_utils.h" typedef struct private_tkm_listener_t private_tkm_listener_t; @@ -56,9 +59,21 @@ METHOD(listener_t, authorize, bool, *success = FALSE; } - DBG1(DBG_IKE, "TKM based authentication successful" - " for ISA context %llu", isa_id); - *success = TRUE; + signature_type signature; + chunk_to_sequence(auth, &signature); + if (ike_isa_auth_psk(isa_id, signature) != TKM_OK) + { + DBG1(DBG_IKE, "TKM based authentication failed" + " for ISA context %llu", isa_id); + *success = FALSE; + } + else + { + DBG1(DBG_IKE, "TKM based authentication successful" + " for ISA context %llu", isa_id); + *success = TRUE; + } + return TRUE; } -- cgit v1.2.3 From 8f1dfb3d9ea7f3170f62e1bafa17992fcff4fb29 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 7 Sep 2012 15:44:37 +0200 Subject: chunk_map: Store key, value pair in entry_t struct To make the chunk map more robust it now stores a clone of the data chunk given on insertion. The entry struct is needed to properly free the allocated chunk after use. --- src/charon-tkm/src/tkm/tkm_chunk_map.c | 60 +++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_chunk_map.c b/src/charon-tkm/src/tkm/tkm_chunk_map.c index 2a1a944de..03ff22836 100644 --- a/src/charon-tkm/src/tkm/tkm_chunk_map.c +++ b/src/charon-tkm/src/tkm/tkm_chunk_map.c @@ -45,44 +45,73 @@ struct private_tkm_chunk_map_t { }; +/** + * Entry for hashtables + */ +typedef struct { + /** Key chunk */ + chunk_t key; + /** Entry value */ + uint64_t value; +} entry_t; + +/** + * Destroy a hashtable entry + */ +static void entry_destroy(entry_t *this) +{ + chunk_free(&this->key); + free(this); +} + METHOD(tkm_chunk_map_t, insert, void, private_tkm_chunk_map_t * const this, const chunk_t * const data, const uint64_t id) { - uint64_t *value = malloc_thing(uint64_t); - *value = id; + entry_t *entry; + INIT(entry, + .key = chunk_clone(*data), + .value = id + ); this->lock->write_lock(this->lock); - value = this->mappings->put(this->mappings, (void*)data, value); + entry = this->mappings->put(this->mappings, (void*)&entry->key, entry); this->lock->unlock(this->lock); - if (value) + if (entry) { - free(value); + entry_destroy(entry); } } METHOD(tkm_chunk_map_t, get_id, uint64_t, private_tkm_chunk_map_t * const this, chunk_t *data) { - uint64_t *value; + entry_t *entry; this->lock->read_lock(this->lock); - value = this->mappings->get(this->mappings, data); + entry = this->mappings->get(this->mappings, data); this->lock->unlock(this->lock); - return value == NULL ? 0 : *value; + if (!entry) + { + return 0; + } + + return entry->value; } METHOD(tkm_chunk_map_t, remove_, bool, private_tkm_chunk_map_t * const this, chunk_t *data) { + entry_t *entry; + this->lock->write_lock(this->lock); - uint64_t *value = this->mappings->remove(this->mappings, data); + entry = this->mappings->remove(this->mappings, data); this->lock->unlock(this->lock); - if (value) + if (entry) { - free(value); + entry_destroy(entry); return TRUE; } else @@ -94,21 +123,20 @@ METHOD(tkm_chunk_map_t, remove_, bool, METHOD(tkm_chunk_map_t, destroy, void, private_tkm_chunk_map_t *this) { - uint64_t *value; + entry_t *entry; enumerator_t *enumerator; this->lock->write_lock(this->lock); enumerator = this->mappings->create_enumerator(this->mappings); - while (enumerator->enumerate(enumerator, NULL, &value)) + while (enumerator->enumerate(enumerator, NULL, &entry)) { - this->mappings->remove_at(this->mappings, enumerator); - free(value); + entry_destroy(entry); } enumerator->destroy(enumerator); this->lock->unlock(this->lock); - this->lock->destroy(this->lock); this->mappings->destroy(this->mappings); + this->lock->destroy(this->lock); free(this); } -- cgit v1.2.3 From 8a780242e2b631ca8062267380ec08781438e720 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 7 Sep 2012 14:58:35 +0200 Subject: Add TKM kernel ipsec skeleton The existing kernel netlink ipsec interface is currently used as proxy to perform the actual work. It will be gradually removed as the TKM implements the needed features. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 199 ++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_kernel_ipsec.h | 42 +++++++ 2 files changed, 241 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_kernel_ipsec.c create mode 100644 src/charon-tkm/src/tkm/tkm_kernel_ipsec.h (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c new file mode 100644 index 000000000..7036b8979 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -0,0 +1,199 @@ +/* + * 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 . + * + * 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 +#include + +#include "tkm_kernel_ipsec.h" + +typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t; + +/** + * Private variables and functions of TKM kernel ipsec instance. + */ +struct private_tkm_kernel_ipsec_t { + + /** + * Public tkm_kernel_ipsec interface. + */ + tkm_kernel_ipsec_t public; + + /** + * Kernel interface proxy (will be removed). + */ + kernel_netlink_ipsec_t *proxy; + +}; + +METHOD(kernel_ipsec_t, get_spi, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) +{ + DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid); + return this->proxy->interface.get_spi(&this->proxy->interface, src, dst, + protocol, reqid, spi); +} + +METHOD(kernel_ipsec_t, get_cpi, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t reqid, u_int16_t *cpi) +{ + return NOT_SUPPORTED; +} + +METHOD(kernel_ipsec_t, add_sa, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool encap, bool esn, bool inbound, + traffic_selector_t* src_ts, traffic_selector_t* dst_ts) +{ + DBG1(DBG_KNL, "adding child SA with SPI %.8x and reqid {%u}", ntohl(spi), + reqid); + return this->proxy->interface.add_sa(&this->proxy->interface, src, dst, spi, + protocol, reqid, mark, tfc, lifetime, + enc_alg, enc_key, int_alg, int_key, + mode, ipcomp, cpi, encap, esn, inbound, + src_ts, dst_ts); +} + +METHOD(kernel_ipsec_t, query_sa, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes, + u_int64_t *packets) +{ + return NOT_SUPPORTED; +} + +METHOD(kernel_ipsec_t, del_sa, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) +{ + DBG1(DBG_KNL, "deleting child SA with SPI %.8x", ntohl(spi)); + return this->proxy->interface.del_sa(&this->proxy->interface, src, dst, spi, + protocol, cpi, mark); +} + +METHOD(kernel_ipsec_t, update_sa, status_t, + private_tkm_kernel_ipsec_t *this, u_int32_t spi, u_int8_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, + bool old_encap, bool new_encap, mark_t mark) +{ + return NOT_SUPPORTED; +} + +METHOD(kernel_ipsec_t, flush_sas, status_t, + private_tkm_kernel_ipsec_t *this) +{ + DBG1(DBG_KNL, "flushing child SA entries"); + return this->proxy->interface.flush_sas(&this->proxy->interface); +} + +METHOD(kernel_ipsec_t, add_policy, status_t, + private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) +{ + return this->proxy->interface.add_policy(&this->proxy->interface, src, dst, + src_ts, dst_ts, direction, type, + sa, mark, priority); +} + +METHOD(kernel_ipsec_t, query_policy, status_t, + private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) +{ + return NOT_SUPPORTED; +} + +METHOD(kernel_ipsec_t, del_policy, status_t, + private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid, + mark_t mark, policy_priority_t prio) +{ + return this->proxy->interface.del_policy(&this->proxy->interface, src_ts, + dst_ts, direction, reqid, mark, + prio); +} + +METHOD(kernel_ipsec_t, flush_policies, status_t, + private_tkm_kernel_ipsec_t *this) +{ + return this->proxy->interface.flush_policies(&this->proxy->interface); +} + + +METHOD(kernel_ipsec_t, bypass_socket, bool, + private_tkm_kernel_ipsec_t *this, int fd, int family) +{ + return this->proxy->interface.bypass_socket(&this->proxy->interface, fd, + family); +} + +METHOD(kernel_ipsec_t, enable_udp_decap, bool, + private_tkm_kernel_ipsec_t *this, int fd, int family, u_int16_t port) +{ + return this->proxy->interface.enable_udp_decap(&this->proxy->interface, fd, + family, port); +} + +METHOD(kernel_ipsec_t, destroy, void, + private_tkm_kernel_ipsec_t *this) +{ + this->proxy->interface.destroy(&this->proxy->interface); + free(this); +} + +/* + * Described in header. + */ +tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() +{ + private_tkm_kernel_ipsec_t *this; + + INIT(this, + .public = { + .interface = { + .get_spi = _get_spi, + .get_cpi = _get_cpi, + .add_sa = _add_sa, + .update_sa = _update_sa, + .query_sa = _query_sa, + .del_sa = _del_sa, + .flush_sas = _flush_sas, + .add_policy = _add_policy, + .query_policy = _query_policy, + .del_policy = _del_policy, + .flush_policies = _flush_policies, + .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, + .destroy = _destroy, + }, + }, + .proxy = kernel_netlink_ipsec_create(), + ); + + if (!this->proxy) + { + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h new file mode 100644 index 000000000..bb30d1c61 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.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 . + * + * 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_KERNEL_IPSEC_H_ +#define TKM_KERNEL_IPSEC_H_ + +#include + +typedef struct tkm_kernel_ipsec_t tkm_kernel_ipsec_t; + +/** + * TKM implementation of the kernel ipsec interface. + */ +struct tkm_kernel_ipsec_t { + + /** + * Implements kernel_ipsec_t interface + */ + kernel_ipsec_t interface; +}; + +/** + * Create a TKM kernel ipsec interface instance. + * + * @return tkm_kernel_ipsec_t instance + */ +tkm_kernel_ipsec_t *tkm_kernel_ipsec_create(); + +#endif /** TKM_KERNEL_IPSEC_H_ */ -- cgit v1.2.3 From cc169cb16e6d4a45fc024a90df2bc0e26824f2a1 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 7 Sep 2012 15:17:25 +0200 Subject: Register TKM kernel ipsec interface in charon-tkm --- src/charon-tkm/src/charon-tkm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index f2a58b21e..0782bda13 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -38,6 +38,7 @@ #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" #include "tkm_listener.h" +#include "tkm_kernel_ipsec.h" /** * TKM bus listener for IKE authorize events. @@ -284,6 +285,8 @@ int main(int argc, char *argv[]) PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), PLUGIN_PROVIDE(DH, MODP_3072_BIT), PLUGIN_PROVIDE(DH, MODP_4096_BIT), + PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), }; lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE); -- cgit v1.2.3 From b94a0befafbddb49497456ba8b5c9d45bf293785 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 10 Sep 2012 10:43:05 +0200 Subject: Implement CHILD SA key derivation using TKM ESP SAs are created when adding CHILD SAs via the kernel ipsec interface. The encr_i key is used to transfer the context id of the parent IKE SA from the keymat to the TKM kernel ipsec interface. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 35 ++++++++++++++++++++++++++++--- src/charon-tkm/src/tkm/tkm_keymat.c | 11 ++++++++-- src/charon-tkm/src/tkm/tkm_types.h | 27 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 src/charon-tkm/src/tkm/tkm_types.h (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 7036b8979..421d2f3fc 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -16,7 +16,11 @@ #include #include +#include +#include +#include "tkm_types.h" +#include "tkm_keymat.h" #include "tkm_kernel_ipsec.h" typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t; @@ -36,6 +40,11 @@ struct private_tkm_kernel_ipsec_t { */ kernel_netlink_ipsec_t *proxy; + /** + * Local CHILD SA SPI. + */ + uint32_t esp_spi_loc; + }; METHOD(kernel_ipsec_t, get_spi, status_t, @@ -62,11 +71,30 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int16_t cpi, bool encap, bool esn, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) { - DBG1(DBG_KNL, "adding child SA with SPI %.8x and reqid {%u}", ntohl(spi), - reqid); + if (inbound && this->esp_spi_loc == 0) + { + DBG1(DBG_KNL, "store local child SA SPI for installation", ntohl(spi)); + this->esp_spi_loc = spi; + this->proxy->interface.add_sa(&this->proxy->interface, src, dst, spi, + protocol, reqid, mark, tfc, lifetime, + enc_alg, enc_key, int_alg, int_key, mode, + ipcomp, cpi, encap, esn, inbound, src_ts, + dst_ts); + return SUCCESS; + } + const esa_info_t esa = *(esa_info_t *)(enc_key.ptr); + DBG1(DBG_KNL, "adding child SA (isa: %llu, esp_spi_loc: %x, esp_spi_rem:" + " %x)", esa.isa_id, ntohl(this->esp_spi_loc), ntohl(spi)); + if (ike_esa_create_first (1, esa.isa_id, 1, 1, ntohl(this->esp_spi_loc), + ntohl(spi)) != TKM_OK) + { + DBG1(DBG_KNL, "child SA creation failed"); + return FAILED; + } + this->esp_spi_loc = 0; return this->proxy->interface.add_sa(&this->proxy->interface, src, dst, spi, protocol, reqid, mark, tfc, lifetime, - enc_alg, enc_key, int_alg, int_key, + enc_alg, esa.enc_key, int_alg, int_key, mode, ipcomp, cpi, encap, esn, inbound, src_ts, dst_ts); } @@ -186,6 +214,7 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() .destroy = _destroy, }, }, + .esp_spi_loc = 0, .proxy = kernel_netlink_ipsec_create(), ); diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index b36353b5c..a2d40a86c 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -20,6 +20,7 @@ #include #include "tkm.h" +#include "tkm_types.h" #include "tkm_utils.h" #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" @@ -291,8 +292,14 @@ METHOD(tkm_keymat_t, derive_child_keys, bool, chunk_t *encr_r, chunk_t *integ_r) { DBG1(DBG_CHD, "deriving child keys"); - return this->proxy->derive_child_keys(this->proxy, proposal, dh, nonce_i, - nonce_r, encr_i, integ_i, encr_r, integ_r); + *encr_i = chunk_alloc(sizeof(esa_info_t)); + (*(esa_info_t*)(encr_i->ptr)).isa_id = this->isa_ctx_id; + const bool result = this->proxy->derive_child_keys(this->proxy, proposal, + dh, nonce_i, nonce_r, + &(*(esa_info_t*)(encr_i->ptr)).enc_key, + integ_i, encr_r, + integ_r); + return result; } METHOD(keymat_t, get_aead, aead_t*, diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h new file mode 100644 index 000000000..8c65348af --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -0,0 +1,27 @@ +/* + * 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 . + * + * 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_TYPES_H_ +#define TKM_TYPES_H_ + +typedef struct esa_info_t esa_info_t; + +struct esa_info_t { + isa_id_type isa_id; + chunk_t enc_key; +}; + +#endif /** TKM_TYPES_H_ */ -- cgit v1.2.3 From a642e3ba27dcc21c0ead3aa7c8980375f5ae2685 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 11 Sep 2012 18:24:21 +0200 Subject: Avoid proxy for bypass_socket, enable_udp_decap This is in preparation for the removal of the netlink kernel proxy. The code is copied as-is from the kernel_netlink_ipsec plugin. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 51 ++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 421d2f3fc..9eac308b6 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -14,6 +14,9 @@ * for more details. */ +#include +#include +#include #include #include #include @@ -170,15 +173,55 @@ METHOD(kernel_ipsec_t, flush_policies, status_t, METHOD(kernel_ipsec_t, bypass_socket, bool, private_tkm_kernel_ipsec_t *this, int fd, int family) { - return this->proxy->interface.bypass_socket(&this->proxy->interface, fd, - family); + struct xfrm_userpolicy_info policy; + u_int sol, ipsec_policy; + + switch (family) + { + case AF_INET: + sol = SOL_IP; + ipsec_policy = IP_XFRM_POLICY; + break; + case AF_INET6: + sol = SOL_IPV6; + ipsec_policy = IPV6_XFRM_POLICY; + break; + default: + return FALSE; + } + + memset(&policy, 0, sizeof(policy)); + policy.action = XFRM_POLICY_ALLOW; + policy.sel.family = family; + + policy.dir = XFRM_POLICY_OUT; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + policy.dir = XFRM_POLICY_IN; + if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) + { + DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", + strerror(errno)); + return FALSE; + } + return TRUE; } METHOD(kernel_ipsec_t, enable_udp_decap, bool, private_tkm_kernel_ipsec_t *this, int fd, int family, u_int16_t port) { - return this->proxy->interface.enable_udp_decap(&this->proxy->interface, fd, - family, port); + int type = UDP_ENCAP_ESPINUDP; + + if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + { + DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno)); + return FALSE; + } + return TRUE; } METHOD(kernel_ipsec_t, destroy, void, -- cgit v1.2.3 From 6c237edb9a23d521cd0e32838a6441c73361dd63 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 11 Sep 2012 18:32:50 +0200 Subject: Remove netlink proxy from TKM kernel interface The TKM is now able to manage simple child SAs, so there is no need for the netlink proxy anymore. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 46 +++++++------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 9eac308b6..3a58e23fe 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -38,11 +38,6 @@ struct private_tkm_kernel_ipsec_t { */ tkm_kernel_ipsec_t public; - /** - * Kernel interface proxy (will be removed). - */ - kernel_netlink_ipsec_t *proxy; - /** * Local CHILD SA SPI. */ @@ -55,8 +50,9 @@ METHOD(kernel_ipsec_t, get_spi, status_t, u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) { DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid); - return this->proxy->interface.get_spi(&this->proxy->interface, src, dst, - protocol, reqid, spi); + /* fake SPI for now */ + *spi = 92726226; + return SUCCESS; } METHOD(kernel_ipsec_t, get_cpi, status_t, @@ -78,11 +74,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "store local child SA SPI for installation", ntohl(spi)); this->esp_spi_loc = spi; - this->proxy->interface.add_sa(&this->proxy->interface, src, dst, spi, - protocol, reqid, mark, tfc, lifetime, - enc_alg, enc_key, int_alg, int_key, mode, - ipcomp, cpi, encap, esn, inbound, src_ts, - dst_ts); return SUCCESS; } const esa_info_t esa = *(esa_info_t *)(enc_key.ptr); @@ -95,11 +86,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, return FAILED; } this->esp_spi_loc = 0; - return this->proxy->interface.add_sa(&this->proxy->interface, src, dst, spi, - protocol, reqid, mark, tfc, lifetime, - enc_alg, esa.enc_key, int_alg, int_key, - mode, ipcomp, cpi, encap, esn, inbound, - src_ts, dst_ts); + return SUCCESS; } METHOD(kernel_ipsec_t, query_sa, status_t, @@ -115,8 +102,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t, u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) { DBG1(DBG_KNL, "deleting child SA with SPI %.8x", ntohl(spi)); - return this->proxy->interface.del_sa(&this->proxy->interface, src, dst, spi, - protocol, cpi, mark); + return SUCCESS; } METHOD(kernel_ipsec_t, update_sa, status_t, @@ -131,7 +117,7 @@ METHOD(kernel_ipsec_t, flush_sas, status_t, private_tkm_kernel_ipsec_t *this) { DBG1(DBG_KNL, "flushing child SA entries"); - return this->proxy->interface.flush_sas(&this->proxy->interface); + return SUCCESS; } METHOD(kernel_ipsec_t, add_policy, status_t, @@ -140,9 +126,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark, policy_priority_t priority) { - return this->proxy->interface.add_policy(&this->proxy->interface, src, dst, - src_ts, dst_ts, direction, type, - sa, mark, priority); + return SUCCESS; } METHOD(kernel_ipsec_t, query_policy, status_t, @@ -158,15 +142,13 @@ METHOD(kernel_ipsec_t, del_policy, status_t, traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid, mark_t mark, policy_priority_t prio) { - return this->proxy->interface.del_policy(&this->proxy->interface, src_ts, - dst_ts, direction, reqid, mark, - prio); + return SUCCESS; } METHOD(kernel_ipsec_t, flush_policies, status_t, private_tkm_kernel_ipsec_t *this) { - return this->proxy->interface.flush_policies(&this->proxy->interface); + return SUCCESS; } @@ -227,7 +209,6 @@ METHOD(kernel_ipsec_t, enable_udp_decap, bool, METHOD(kernel_ipsec_t, destroy, void, private_tkm_kernel_ipsec_t *this) { - this->proxy->interface.destroy(&this->proxy->interface); free(this); } @@ -258,14 +239,7 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() }, }, .esp_spi_loc = 0, - .proxy = kernel_netlink_ipsec_create(), ); - if (!this->proxy) - { - free(this); - return NULL; - } - return &this->public; } -- cgit v1.2.3 From a61ae27d165edadd1e177e60441d11a636fa7d44 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 11 Sep 2012 19:04:55 +0200 Subject: Remove keymat proxy from TKM keymat Since the TKM completely handles key derivation and installation there is no need for the keymat proxy anymore. --- src/charon-tkm/src/tkm/tkm_keymat.c | 39 +++++++++++-------------------------- src/charon-tkm/src/tkm/tkm_types.h | 1 - 2 files changed, 11 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index a2d40a86c..0b9612c85 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -37,11 +36,6 @@ struct private_tkm_keymat_t { */ tkm_keymat_t public; - /** - * IKEv2 keymat proxy (will be removed). - */ - keymat_v2_t *proxy; - /** * IKE_SA Role, initiator or responder. */ @@ -271,19 +265,14 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, /* TODO: Add failure handler (see keymat_v2.c) */ - if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i, - nonce_r, id, rekey_function, rekey_skd)) + tkm->chunk_map->remove(tkm->chunk_map, nonce); + if (ike_nc_reset(nc_id) != TKM_OK) { - tkm->chunk_map->remove(tkm->chunk_map, nonce); - if (ike_nc_reset(nc_id) != TKM_OK) - { - DBG1(DBG_IKE, "failed to reset nonce context %llu", nc_id); - } - tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id); - - return TRUE; + DBG1(DBG_IKE, "failed to reset nonce context %llu", nc_id); } - return FALSE; + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id); + + return TRUE; } METHOD(tkm_keymat_t, derive_child_keys, bool, @@ -294,12 +283,7 @@ METHOD(tkm_keymat_t, derive_child_keys, bool, DBG1(DBG_CHD, "deriving child keys"); *encr_i = chunk_alloc(sizeof(esa_info_t)); (*(esa_info_t*)(encr_i->ptr)).isa_id = this->isa_ctx_id; - const bool result = this->proxy->derive_child_keys(this->proxy, proposal, - dh, nonce_i, nonce_r, - &(*(esa_info_t*)(encr_i->ptr)).enc_key, - integ_i, encr_r, - integ_r); - return result; + return TRUE; } METHOD(keymat_t, get_aead, aead_t*, @@ -313,15 +297,16 @@ METHOD(tkm_keymat_t, get_auth_octets, bool, chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) { DBG1(DBG_IKE, "returning auth octets"); - return this->proxy->get_auth_octets(this->proxy, verify, ike_sa_init, nonce, - id, reserved, octets); + *octets = chunk_empty; + return TRUE; } METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t, private_tkm_keymat_t *this, chunk_t *skd) { DBG1(DBG_IKE, "returning skd"); - return this->proxy->get_skd(this->proxy, skd); + *skd = chunk_empty; + return PRF_HMAC_SHA2_512; } METHOD(tkm_keymat_t, get_psk_sig, bool, @@ -365,7 +350,6 @@ METHOD(keymat_t, destroy, void, DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); chunk_free(&this->auth_payload); - this->proxy->keymat.destroy(&this->proxy->keymat); free(this); } @@ -416,7 +400,6 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), .ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE), .auth_payload = chunk_empty, - .proxy = keymat_v2_create(initiator), ); if (!this->isa_ctx_id || !this->ae_ctx_id) diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index 8c65348af..a33066444 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -21,7 +21,6 @@ typedef struct esa_info_t esa_info_t; struct esa_info_t { isa_id_type isa_id; - chunk_t enc_key; }; #endif /** TKM_TYPES_H_ */ -- cgit v1.2.3 From db97fd74d3185b02b25942972a181ee600d6b9b5 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 11 Sep 2012 19:13:29 +0200 Subject: Do not return shared secret in TKM Diffie-Hellman Since the TKM handles all relevant key material, charon-tkm must not have access to it anymore. Thus the ike_dh_get_shared_secret operation is not available anymore. --- src/charon-tkm/src/tkm/tkm_diffie_hellman.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c index cef53464c..19f57de01 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c @@ -61,13 +61,7 @@ METHOD(diffie_hellman_t, get_my_public_value, void, METHOD(diffie_hellman_t, get_shared_secret, status_t, private_tkm_diffie_hellman_t *this, chunk_t *secret) { - dh_key_type shared_secret; - if (ike_dh_get_shared_secret(this->context_id, &shared_secret) != TKM_OK) - { - return FAILED; - } - - sequence_to_chunk(&shared_secret.data[0], shared_secret.size, secret); + *secret = chunk_empty; return SUCCESS; } -- cgit v1.2.3 From 6ed5c3bb1e5229e23d4810ca45bdf5ec833bb187 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 11 Sep 2012 19:17:23 +0200 Subject: charon-tkm: Register kernel_netlink_net Explicitly register kernel netlink net implementation and avoid loading the whole kernel-netlink plugin since the kernel netlink ipsec part is unwanted. --- src/charon-tkm/Makefile.am | 1 - src/charon-tkm/src/charon-tkm.c | 4 ++++ src/charon-tkm/tests/keymat_tests.c | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 1b5dfdf2b..6c7359323 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -25,7 +25,6 @@ PLUGINS = \ aes \ constraints \ hmac \ - kernel-netlink \ pem \ pkcs1 \ pkcs8 \ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 0782bda13..1d21e7daf 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -287,6 +288,9 @@ int main(int argc, char *argv[]) PLUGIN_PROVIDE(DH, MODP_4096_BIT), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + }; lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE); diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index 0fde2fb6e..0d74ad55c 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -19,12 +19,14 @@ #include #include #include +#include #include #include "tkm.h" #include "tkm_nonceg.h" #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" +#include "tkm_kernel_ipsec.h" START_TEST(test_derive_ike_keys) { @@ -39,6 +41,10 @@ START_TEST(test_derive_ike_keys) PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), PLUGIN_PROVIDE(DH, MODP_3072_BIT), PLUGIN_PROVIDE(DH, MODP_4096_BIT), + PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), }; lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, countof(features), TRUE); -- cgit v1.2.3 From d0ab667c99a7ac4ecfe6cb0f941843a6751a600e Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 12 Sep 2012 11:52:08 +0200 Subject: Use rng to generate local ESP SPIs --- src/charon-tkm/src/charon-tkm.c | 2 +- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 20 +++++++++++++++++--- src/charon-tkm/tests/keymat_tests.c | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 1d21e7daf..f7b59008c 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -28,7 +28,6 @@ #include #include #include - #include #include #include @@ -288,6 +287,7 @@ int main(int argc, char *argv[]) PLUGIN_PROVIDE(DH, MODP_4096_BIT), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), PLUGIN_PROVIDE(CUSTOM, "kernel-net"), diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 3a58e23fe..ce6a26e5b 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -38,6 +38,11 @@ struct private_tkm_kernel_ipsec_t { */ tkm_kernel_ipsec_t public; + /** + * RNG used for SPI generation. + */ + rng_t *rng; + /** * Local CHILD SA SPI. */ @@ -50,9 +55,9 @@ METHOD(kernel_ipsec_t, get_spi, status_t, u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) { DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid); - /* fake SPI for now */ - *spi = 92726226; - return SUCCESS; + const bool result = this->rng->get_bytes(this->rng, sizeof(u_int32_t), + (u_int8_t *)spi); + return result ? SUCCESS : FAILED; } METHOD(kernel_ipsec_t, get_cpi, status_t, @@ -209,6 +214,7 @@ METHOD(kernel_ipsec_t, enable_udp_decap, bool, METHOD(kernel_ipsec_t, destroy, void, private_tkm_kernel_ipsec_t *this) { + DESTROY_IF(this->rng); free(this); } @@ -238,8 +244,16 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() .destroy = _destroy, }, }, + .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), .esp_spi_loc = 0, ); + if (!this->rng) + { + DBG1(DBG_KNL, "unable to create RNG"); + destroy(this); + return NULL; + } + return &this->public; } diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index 0d74ad55c..82ecf1ce3 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -43,6 +43,7 @@ START_TEST(test_derive_ike_keys) PLUGIN_PROVIDE(DH, MODP_4096_BIT), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), PLUGIN_PROVIDE(CUSTOM, "kernel-net"), }; -- cgit v1.2.3 From d1c08227597fe26044abb81709efd193e896e8ce Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 14 Sep 2012 10:29:38 +0200 Subject: Add TKM_CTX_ESA (ESP SA context id) --- src/charon-tkm/src/tkm/tkm.c | 2 +- src/charon-tkm/src/tkm/tkm_id_manager.c | 7 ++++--- src/charon-tkm/src/tkm/tkm_id_manager.h | 2 ++ src/charon-tkm/tests/id_manager_tests.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index f2ffd2838..5fc554e13 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -75,7 +75,7 @@ bool tkm_init() return FALSE; } - const tkm_limits_t limits = {nc, dh, isa, ae}; + const tkm_limits_t limits = {nc, dh, isa, ae, esa}; INIT(this, .public = { diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 6120c32a7..24513ebf1 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -22,12 +22,13 @@ #define TKM_LIMIT 100 -ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_AE, +ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ESA, "NONCE_CONTEXT", "DH_CONTEXT", "ISA_CONTEXT", - "AE_CONTEXT"); -ENUM_END(tkm_context_kind_names, TKM_CTX_AE); + "AE_CONTEXT", + "ESA_CONTEXT"); +ENUM_END(tkm_context_kind_names, TKM_CTX_ESA); typedef struct private_tkm_id_manager_t private_tkm_id_manager_t; diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 17ca01720..716e91d79 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -34,6 +34,8 @@ enum tkm_context_kind_t { TKM_CTX_ISA, /** Authenticated Endpoint context */ TKM_CTX_AE, + /** ESP SA context */ + TKM_CTX_ESA, /** helper to determine the number of elements in this enum */ TKM_CTX_MAX, diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index c4d53661f..fd34bf91f 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -18,7 +18,7 @@ #include "tkm_id_manager.h" -static const tkm_limits_t limits = {125, 100, 30, 200}; +static const tkm_limits_t limits = {125, 100, 30, 200, 42}; START_TEST(test_id_mgr_creation) { -- cgit v1.2.3 From 1e13904f457a1d4a97757e695bac7e9cb683b90d Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 14 Sep 2012 14:59:04 +0200 Subject: Implement TKM kernel SA database (SAD) The TKM kernel SAD (security association database) stores information about CHILD SAs. --- src/charon-tkm/src/tkm/tkm_kernel_sad.c | 250 ++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_kernel_sad.h | 78 ++++++++++ src/charon-tkm/tests/kernel_sad_tests.c | 122 ++++++++++++++++ src/charon-tkm/tests/test_runner.c | 1 + src/charon-tkm/tests/test_runner.h | 1 + 5 files changed, 452 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_kernel_sad.c create mode 100644 src/charon-tkm/src/tkm/tkm_kernel_sad.h create mode 100644 src/charon-tkm/tests/kernel_sad_tests.c (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.c b/src/charon-tkm/src/tkm/tkm_kernel_sad.c new file mode 100644 index 000000000..02b6ddc7c --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.c @@ -0,0 +1,250 @@ +/* + * 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 . + * + * 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 +#include +#include + +#include "tkm_kernel_sad.h" + +typedef struct private_tkm_kernel_sad_t private_tkm_kernel_sad_t; + +/** + * Private data of tkm_kernel_sad. + */ +struct private_tkm_kernel_sad_t { + + /** + * Public functions. + */ + tkm_kernel_sad_t public; + + /** + * Linked list of SAD entries. + */ + linked_list_t *data; + + /** + * Lock used to protect SA data. + */ + mutex_t *mutex; + +}; + +typedef struct sad_entry_t sad_entry_t; + +/** + * Data structure holding all information of an SAD entry. + */ +struct sad_entry_t { + + /** + * ESA identifier. + */ + esa_id_type esa_id; + + /** + * Source address of CHILD SA. + */ + host_t *src; + + /** + * Destination address of CHILD SA. + */ + host_t *dst; + + /** + * SPI of CHILD SA. + */ + u_int32_t spi; + + /** + * Protocol of CHILD SA (ESP/AH). + */ + u_int8_t proto; + +}; + +/** + * Destroy an sad_entry_t object. + */ +static void sad_entry_destroy(sad_entry_t *entry) +{ + if (entry) + { + DESTROY_IF(entry->src); + DESTROY_IF(entry->dst); + free(entry); + } +} + +/** + * Find a list entry with given src, dst, spi and proto values. + */ +static bool sad_entry_match(sad_entry_t * const entry, const host_t * const src, + const host_t * const dst, const u_int32_t * const spi, + const u_int8_t * const proto) +{ + if (entry->src == NULL || entry->dst == NULL) + { + return FALSE; + } + + return src->ip_equals(entry->src, (host_t *)src) && + dst->ip_equals(entry->dst, (host_t *)dst) && + entry->spi == *spi && entry->proto == *proto; +} + +/** + * Compare two SAD entries for equality. + */ +static bool sad_entry_equal(sad_entry_t * const left, sad_entry_t * const right) +{ + if (left->src == NULL || left->dst == NULL || right->src == NULL || + right->dst == NULL) + { + return FALSE; + } + return left->esa_id == right->esa_id && + left->src->ip_equals(left->src, right->src) && + left->dst->ip_equals(left->dst, right->dst) && + left->spi == right->spi && left->proto == right->proto; +} + +METHOD(tkm_kernel_sad_t, insert, bool, + private_tkm_kernel_sad_t * const this, const esa_id_type esa_id, + const host_t * const src, const host_t * const dst, const u_int32_t spi, + const u_int8_t proto) +{ + + sad_entry_t *new_entry; + INIT(new_entry, + .esa_id = esa_id, + .src = (host_t *)src, + .dst = (host_t *)dst, + .spi = spi, + .proto = proto, + ); + + this->mutex->lock(this->mutex); + const status_t result = this->data->find_first(this->data, + (linked_list_match_t)sad_entry_equal, + NULL, new_entry); + if (result == NOT_FOUND) + { + DBG3(DBG_KNL, "inserting SAD entry (esa: %llu, src: %H, dst: %H, " + "spi: %x, proto: %u)", esa_id, src, dst, ntohl(spi), proto); + new_entry->src = src->clone((host_t *)src); + new_entry->dst = dst->clone((host_t *)dst); + this->data->insert_last(this->data, new_entry); + } + else + { + DBG1(DBG_KNL, "SAD entry with esa id %llu already exists!", esa_id); + free(new_entry); + } + this->mutex->unlock(this->mutex); + return result == NOT_FOUND; +} + +METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type, + private_tkm_kernel_sad_t * const this, const host_t * const src, + const host_t * const dst, const u_int32_t spi, const u_int8_t proto) +{ + esa_id_type id = 0; + sad_entry_t *entry = NULL; + + this->mutex->lock(this->mutex); + const status_t res = this->data->find_first(this->data, + (linked_list_match_t)sad_entry_match, + (void**)&entry, src, dst, &spi, + &proto); + if (res == SUCCESS && entry) + { + id = entry->esa_id; + DBG3(DBG_KNL, "getting ESA id of SAD entry (esa: %llu, src: %H, " + "dst: %H, spi: %x, proto: %u)", id, src, dst, ntohl(spi), + proto); + } + else + { + DBG3(DBG_KNL, "no SAD entry found"); + } + this->mutex->unlock(this->mutex); + return id; +} + +METHOD(tkm_kernel_sad_t, _remove, bool, + private_tkm_kernel_sad_t * const this, const esa_id_type esa_id) +{ + sad_entry_t *current; + bool removed = FALSE; + this->mutex->lock(this->mutex); + enumerator_t *enumerator = this->data->create_enumerator(this->data); + while (enumerator->enumerate(enumerator, (void **)¤t)) + { + if (current->esa_id == esa_id) + { + this->data->remove_at(this->data, enumerator); + sad_entry_destroy(current); + removed = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (removed) + { + DBG3(DBG_KNL, "removed SAD entry (esa: %llu)", esa_id); + } + else + { + DBG1(DBG_KNL, "no SAD entry with ESA id %llu found!", esa_id); + } + this->mutex->unlock(this->mutex); + + return removed; +} + + +METHOD(tkm_kernel_sad_t, destroy, void, + private_tkm_kernel_sad_t *this) +{ + this->mutex->destroy(this->mutex); + this->data->destroy_function(this->data, (void*)sad_entry_destroy); + free(this); +} + +/* + * see header file + */ +tkm_kernel_sad_t *tkm_kernel_sad_create() +{ + private_tkm_kernel_sad_t *this; + + INIT(this, + .public = { + .insert = _insert, + .get_esa_id = _get_esa_id, + .remove = __remove, + .destroy = _destroy, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .data = linked_list_create(), + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.h b/src/charon-tkm/src/tkm/tkm_kernel_sad.h new file mode 100644 index 000000000..6863584f4 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.h @@ -0,0 +1,78 @@ +/* + * 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 . + * + * 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_KERNEL_SAD_H_ +#define TKM_KERNEL_SAD_H_ + +#include +#include + +typedef struct tkm_kernel_sad_t tkm_kernel_sad_t; + +/** + * The TKM kernel SAD (security association database) stores information about + * CHILD SAs. + */ +struct tkm_kernel_sad_t { + + /** + * Insert new SAD entry with specified parameters. + * + * @param esa_id ESP SA context identifier + * @param src source address of CHILD SA + * @param dst destination address of CHILD SA + * @param spi SPI of CHILD SA + * @param proto protocol of CHILD SA (ESP/AH) + * @return TRUE if entry was inserted, FALSE otherwise + */ + bool (*insert)(tkm_kernel_sad_t * const this, const esa_id_type esa_id, + const host_t * const src, const host_t * const dst, + const u_int32_t spi, const u_int8_t proto); + + /** + * Get ESA id for entry with given parameters. + * + * @param src source address of CHILD SA + * @param dst destination address of CHILD SA + * @param spi SPI of CHILD SA + * @param proto protocol of CHILD SA (ESP/AH) + * @return ESA id of entry if found, 0 otherwise + */ + esa_id_type (*get_esa_id)(tkm_kernel_sad_t * const this, + const host_t * const src, const host_t * const dst, + const u_int32_t spi, const u_int8_t proto); + + /** + * Remove entry with given ESA id from SAD. + * + * @param esa_id ESA identifier of entry to remove + * @return TRUE if entry was removed, FALSE otherwise + */ + bool (*remove)(tkm_kernel_sad_t * const this, const esa_id_type esa_id); + + /** + * Destroy a tkm_kernel_sad instance. + */ + void (*destroy)(tkm_kernel_sad_t *this); + +}; + +/** + * Create a TKM kernel SAD instance. + */ +tkm_kernel_sad_t *tkm_kernel_sad_create(); + +#endif /** TKM_KERNEL_SAD_H_ */ diff --git a/src/charon-tkm/tests/kernel_sad_tests.c b/src/charon-tkm/tests/kernel_sad_tests.c new file mode 100644 index 000000000..11785602d --- /dev/null +++ b/src/charon-tkm/tests/kernel_sad_tests.c @@ -0,0 +1,122 @@ +/* + * 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 . + * + * 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 + +#include "tkm_kernel_sad.h" + +START_TEST(test_sad_creation) +{ + tkm_kernel_sad_t *sad = NULL; + + sad = tkm_kernel_sad_create(); + fail_if(!sad, "Error creating tkm kernel SAD"); + + sad->destroy(sad); +} +END_TEST + +START_TEST(test_insert) +{ + host_t *addr = host_create_from_string("127.0.0.1", 1024); + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + + fail_unless(sad->insert(sad, 1, addr, addr, 42, 50), + "Error inserting SAD entry"); + + sad->destroy(sad); + addr->destroy(addr); +} +END_TEST + +START_TEST(test_insert_duplicate) +{ + host_t *addr = host_create_from_string("127.0.0.1", 1024); + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + + fail_unless(sad->insert(sad, 1, addr, addr, 42, 50), + "Error inserting SAD entry"); + fail_if(sad->insert(sad, 1, addr, addr, 42, 50), + "Expected error inserting duplicate entry"); + + sad->destroy(sad); + addr->destroy(addr); +} +END_TEST + +START_TEST(test_get_esa_id) +{ + host_t *addr = host_create_from_string("127.0.0.1", 1024); + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + fail_unless(sad->insert(sad, 23, addr, addr, 42, 50), + "Error inserting SAD entry"); + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23, + "Error getting esa id"); + sad->destroy(sad); + addr->destroy(addr); +} +END_TEST + +START_TEST(test_get_esa_id_nonexistent) +{ + host_t *addr = host_create_from_string("127.0.0.1", 1024); + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 0, + "Got esa id for nonexistent SAD entry"); + sad->destroy(sad); + addr->destroy(addr); +} +END_TEST + +START_TEST(test_remove) +{ + host_t *addr = host_create_from_string("127.0.0.1", 1024); + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + fail_unless(sad->insert(sad, 23, addr, addr, 42, 50), + "Error inserting SAD entry"); + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23, + "Error getting esa id"); + fail_unless(sad->remove(sad, 23), + "Error removing SAD entry"); + fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 0, + "Got esa id for removed SAD entry"); + sad->destroy(sad); + addr->destroy(addr); +} +END_TEST + +START_TEST(test_remove_nonexistent) +{ + tkm_kernel_sad_t *sad = tkm_kernel_sad_create(); + fail_if(sad->remove(sad, 1), + "Expected error removing nonexistent SAD entry"); + sad->destroy(sad); +} +END_TEST + +TCase *make_kernel_sad_tests(void) +{ + TCase *tc = tcase_create("Kernel SAD tests"); + tcase_add_test(tc, test_sad_creation); + tcase_add_test(tc, test_insert); + tcase_add_test(tc, test_insert_duplicate); + tcase_add_test(tc, test_get_esa_id); + tcase_add_test(tc, test_get_esa_id_nonexistent); + tcase_add_test(tc, test_remove); + tcase_add_test(tc, test_remove_nonexistent); + + return tc; +} diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index 6ab990d92..b716dc633 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -33,6 +33,7 @@ int main(void) suite_add_tcase(s, make_nonceg_tests()); suite_add_tcase(s, make_diffie_hellman_tests()); suite_add_tcase(s, make_keymat_tests()); + suite_add_tcase(s, make_kernel_sad_tests()); SRunner *sr = srunner_create(s); diff --git a/src/charon-tkm/tests/test_runner.h b/src/charon-tkm/tests/test_runner.h index c8cc0c0db..236a7f2a6 100644 --- a/src/charon-tkm/tests/test_runner.h +++ b/src/charon-tkm/tests/test_runner.h @@ -25,5 +25,6 @@ TCase *make_utility_tests(void); TCase *make_nonceg_tests(void); TCase *make_diffie_hellman_tests(void); TCase *make_keymat_tests(void); +TCase *make_kernel_sad_tests(void); #endif /** TEST_RUNNER_H_ */ -- cgit v1.2.3 From de20230111461e71db1703d376c20f54d726de89 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 14 Sep 2012 15:42:17 +0200 Subject: Use SAD to manage TKM ESA context information An SAD entry is added after successfull creation of a TKM ESA context in the add_sa() function. The corresponding entry is removed in del_sa() using the SAD, src, dst, spi and protocol parameters. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 49 +++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index ce6a26e5b..c97869d9c 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -22,8 +22,10 @@ #include #include +#include "tkm.h" #include "tkm_types.h" #include "tkm_keymat.h" +#include "tkm_kernel_sad.h" #include "tkm_kernel_ipsec.h" typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t; @@ -48,6 +50,11 @@ struct private_tkm_kernel_ipsec_t { */ uint32_t esp_spi_loc; + /** + * CHILD/ESP SA database. + */ + tkm_kernel_sad_t *sad; + }; METHOD(kernel_ipsec_t, get_spi, status_t, @@ -82,12 +89,21 @@ METHOD(kernel_ipsec_t, add_sa, status_t, return SUCCESS; } const esa_info_t esa = *(esa_info_t *)(enc_key.ptr); - DBG1(DBG_KNL, "adding child SA (isa: %llu, esp_spi_loc: %x, esp_spi_rem:" - " %x)", esa.isa_id, ntohl(this->esp_spi_loc), ntohl(spi)); - if (ike_esa_create_first (1, esa.isa_id, 1, 1, ntohl(this->esp_spi_loc), - ntohl(spi)) != TKM_OK) + const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); + DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, esp_spi_rem:" + " %x)", esa_id, esa.isa_id, ntohl(this->esp_spi_loc), ntohl(spi)); + if (!this->sad->insert(this->sad, esa_id, src, dst, spi, protocol)) + { + DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id); + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); + return FAILED; + } + if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(this->esp_spi_loc), + ntohl(spi)) != TKM_OK) { - DBG1(DBG_KNL, "child SA creation failed"); + DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id); + this->sad->remove(this->sad, esa_id); + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); return FAILED; } this->esp_spi_loc = 0; @@ -106,7 +122,20 @@ METHOD(kernel_ipsec_t, del_sa, status_t, private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) { - DBG1(DBG_KNL, "deleting child SA with SPI %.8x", ntohl(spi)); + const esa_id_type esa_id = this->sad->get_esa_id(this->sad, src, dst, spi, + protocol); + if (esa_id) + { + DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id, + ntohl(spi)); + if (ike_esa_reset(esa_id) != TKM_OK) + { + DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id); + return FAILED; + } + this->sad->remove(this->sad, esa_id); + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); + } return SUCCESS; } @@ -215,6 +244,7 @@ METHOD(kernel_ipsec_t, destroy, void, private_tkm_kernel_ipsec_t *this) { DESTROY_IF(this->rng); + DESTROY_IF(this->sad); free(this); } @@ -246,6 +276,7 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() }, .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), .esp_spi_loc = 0, + .sad = tkm_kernel_sad_create(), ); if (!this->rng) @@ -254,6 +285,12 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() destroy(this); return NULL; } + if (!this->sad) + { + DBG1(DBG_KNL, "unable to create SAD"); + destroy(this); + return NULL; + } return &this->public; } -- cgit v1.2.3 From d303221c0b49e28c847fd0f826c7ac39b0530478 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Fri, 14 Sep 2012 17:29:21 +0200 Subject: Extend esa_info_t struct Add additional fields to the esa_info_t struct so the necessary data can be passed from the keymat to the kernel ipsec interface, where ESA creation and key generation using the TKM takes place. The information is used during the inbound add_sa call to create an ESP SA. This makes the hack of storing the local SPI in a kernel interface variable between subsequent add_sa calls unnecessary. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 19 ++++--------- src/charon-tkm/src/tkm/tkm_keymat.c | 38 +++++++++++++++++++++++-- src/charon-tkm/src/tkm/tkm_types.h | 47 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index c97869d9c..eaec4c263 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -45,11 +45,6 @@ struct private_tkm_kernel_ipsec_t { */ rng_t *rng; - /** - * Local CHILD SA SPI. - */ - uint32_t esp_spi_loc; - /** * CHILD/ESP SA database. */ @@ -82,31 +77,28 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int16_t cpi, bool encap, bool esn, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) { - if (inbound && this->esp_spi_loc == 0) + if (!inbound) { - DBG1(DBG_KNL, "store local child SA SPI for installation", ntohl(spi)); - this->esp_spi_loc = spi; return SUCCESS; } const esa_info_t esa = *(esa_info_t *)(enc_key.ptr); const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); - DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, esp_spi_rem:" - " %x)", esa_id, esa.isa_id, ntohl(this->esp_spi_loc), ntohl(spi)); + DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, " + "esp_spi_rem: %x)", esa_id, esa.isa_id, ntohl(spi), ntohl(esa.spi_r)); if (!this->sad->insert(this->sad, esa_id, src, dst, spi, protocol)) { DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id); tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); return FAILED; } - if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(this->esp_spi_loc), - ntohl(spi)) != TKM_OK) + if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(spi), + ntohl(esa.spi_r)) != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id); this->sad->remove(this->sad, esa_id); tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); return FAILED; } - this->esp_spi_loc = 0; return SUCCESS; } @@ -275,7 +267,6 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() }, }, .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), - .esp_spi_loc = 0, .sad = tkm_kernel_sad_create(), ); diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 0b9612c85..f9fd57ae0 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -280,9 +280,41 @@ METHOD(tkm_keymat_t, derive_child_keys, bool, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r) { - DBG1(DBG_CHD, "deriving child keys"); - *encr_i = chunk_alloc(sizeof(esa_info_t)); - (*(esa_info_t*)(encr_i->ptr)).isa_id = this->isa_ctx_id; + esa_info_t *esa_info_i, *esa_info_r; + + dh_id_type dh_id = 0; + if (dh) + { + dh_id = ((tkm_diffie_hellman_t *)dh)->get_id((tkm_diffie_hellman_t *)dh); + } + + INIT(esa_info_i, + .isa_id = this->isa_ctx_id, + .spi_r = proposal->get_spi(proposal), + .nonce_i = chunk_clone(nonce_i), + .nonce_r = chunk_clone(nonce_r), + .is_encr_r = FALSE, + .dh_id = dh_id, + ); + + INIT(esa_info_r, + .isa_id = this->isa_ctx_id, + .spi_r = proposal->get_spi(proposal), + .nonce_i = chunk_clone(nonce_i), + .nonce_r = chunk_clone(nonce_r), + .is_encr_r = TRUE, + .dh_id = dh_id, + ); + + DBG1(DBG_CHD, "passing on esa info (isa: %llu, spi_r: %x, dh_id: %llu)", + esa_info_i->isa_id, ntohl(esa_info_i->spi_r), esa_info_i->dh_id); + + /* store ESA info in encr_i/r, which is passed to add_sa */ + *encr_i = chunk_create((u_char *)esa_info_i, sizeof(esa_info_t)); + *encr_r = chunk_create((u_char *)esa_info_r, sizeof(esa_info_t)); + *integ_i = chunk_empty; + *integ_r = chunk_empty; + return TRUE; } diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index a33066444..65f45cf68 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -17,10 +17,57 @@ #ifndef TKM_TYPES_H_ #define TKM_TYPES_H_ +#include +#include + typedef struct esa_info_t esa_info_t; +/** + * ESP SA info data structure. + * + * This type is used to transfer ESA information from the keymat + * derive_child_keys to the kernel IPsec interface add_sa operation. This is + * necessary because the CHILD SA key derivation and installation is handled + * by a single exchange with the TKM (esa_create*) in add_sa. + * For this purpose the out parameters encr_i and encr_r of the + * derive_child_keys function are (ab)used and the data is stored in these + * data chunks. This is possible since the child SA keys are treated as opaque + * values and handed to the add_sa procedure of the kernel interface as-is + * without any processing. + */ struct esa_info_t { + + /** + * ISA context id. + */ isa_id_type isa_id; + + /** + * Responder SPI of child SA. + */ + esp_spi_type spi_r; + + /** + * Initiator nonce. + */ + chunk_t nonce_i; + + /** + * Responder nonce. + */ + chunk_t nonce_r; + + /** + * Flag specifying if this esa info struct is contained in encr_r. + * It is set to TRUE for encr_r and FALSE for encr_i. + */ + bool is_encr_r; + + /** + * Diffie-Hellman context id. + */ + dh_id_type dh_id; + }; #endif /** TKM_TYPES_H_ */ -- cgit v1.2.3 From 4a1529203b089eb14bb96af8af16dda542ae4f88 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 17 Sep 2012 17:19:58 +0200 Subject: Implement ESA rekeying with and without PFS A child SA is being rekeyed if the esa information passed to the add_sa function contains nonces. If it also contains a valid Diffie-Hellman context id PFS is used. The fact that the encr_r encryption key is passed to add_sa in the inbound case can be used to determine if we are initiator or not by inspecting the is_encr_r flag of the esa information struct. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 110 ++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index eaec4c263..95b378fde 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -23,6 +23,7 @@ #include #include "tkm.h" +#include "tkm_utils.h" #include "tkm_types.h" #include "tkm_keymat.h" #include "tkm_kernel_sad.h" @@ -77,29 +78,112 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int16_t cpi, bool encap, bool esn, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) { - if (!inbound) + if (enc_key.ptr == NULL) { + DBG1(DBG_KNL, "Unable to get ESA information"); + return FAILED; + } + esa_info_t esa = *(esa_info_t *)(enc_key.ptr); + + /* only handle the case where we have both distinct ESP spi's available */ + if (esa.spi_r == spi) + { + chunk_free(&esa.nonce_i); + chunk_free(&esa.nonce_r); return SUCCESS; } - const esa_info_t esa = *(esa_info_t *)(enc_key.ptr); + + /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */ + const bool initiator = esa.is_encr_r && inbound; + + esp_spi_type spi_loc, spi_rem; + host_t *local, *peer; + chunk_t *nonce_loc, *nonce_rem; + if (initiator) + { + spi_loc = spi; + spi_rem = esa.spi_r; + local = dst; + peer = src; + nonce_loc = &esa.nonce_i; + nonce_rem = &esa.nonce_r; + } + else + { + spi_loc = esa.spi_r; + spi_rem = spi; + local = src; + peer = dst; + nonce_loc = &esa.nonce_r; + nonce_rem = &esa.nonce_i; + } + + const nc_id_type nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, + nonce_loc); + const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); - DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, " - "esp_spi_rem: %x)", esa_id, esa.isa_id, ntohl(spi), ntohl(esa.spi_r)); - if (!this->sad->insert(this->sad, esa_id, src, dst, spi, protocol)) + if (!this->sad->insert(this->sad, esa_id, peer, local, spi_loc, protocol)) { DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id); - tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); - return FAILED; + goto sad_failure; } - if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(spi), - ntohl(esa.spi_r)) != TKM_OK) + + /* + * creation of first CHILD SA: + * no nonce and no dh contexts because the ones from the IKE SA are re-used + */ + if (nonce_loc_id == 0 && esa.dh_id == 0) { - DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id); - this->sad->remove(this->sad, esa_id); - tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); - return FAILED; + if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(spi_loc), + ntohl(spi_rem)) != TKM_OK) + { + DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id); + goto failure; + } } + /* creation of child SA without PFS: no dh context */ + else if (nonce_loc_id != 0 && esa.dh_id == 0) + { + nonce_type nc_rem; + chunk_to_sequence(nonce_rem, &nc_rem); + if (ike_esa_create_no_pfs(esa_id, esa.isa_id, 1, 1, nonce_loc_id, + nc_rem, initiator, ntohl(spi_loc), + ntohl(spi_rem)) != TKM_OK) + { + DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id); + goto failure; + } + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id); + } + /* creation of subsequent child SA with PFS: nonce and dh context are set */ + else + { + nonce_type nc_rem; + chunk_to_sequence(nonce_rem, &nc_rem); + if (ike_esa_create(esa_id, esa.isa_id, 1, 1, esa.dh_id, nonce_loc_id, + nc_rem, initiator, ntohl(spi_loc), + ntohl(spi_rem)) != TKM_OK) + { + DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id); + goto failure; + } + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id); + } + DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, " + "esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc), + ntohl(spi_rem), initiator ? "initiator" : "responder"); + chunk_free(&esa.nonce_i); + chunk_free(&esa.nonce_r); + return SUCCESS; + +failure: + this->sad->remove(this->sad, esa_id); +sad_failure: + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id); + chunk_free(&esa.nonce_i); + chunk_free(&esa.nonce_r); + return FAILED; } METHOD(kernel_ipsec_t, query_sa, status_t, -- cgit v1.2.3 From e472129aa363daa3a3b7eb619442c158b1409c3f Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 18 Sep 2012 11:15:16 +0200 Subject: Add test for keymat derive_child_keys operation --- src/charon-tkm/tests/keymat_tests.c | 89 +++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index 82ecf1ce3..3e01e99f1 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -27,6 +27,7 @@ #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" #include "tkm_kernel_ipsec.h" +#include "tkm_types.h" START_TEST(test_derive_ike_keys) { @@ -102,10 +103,98 @@ START_TEST(test_derive_ike_keys) } END_TEST +START_TEST(test_derive_child_keys) +{ + fail_if(!library_init(NULL), "Unable to init library"); + fail_if(!libhydra_init("tkm-tests"), "Unable to init libhydra"); + fail_if(!libcharon_init("tkm-tests"), "Unable to init libcharon"); + + /* Register TKM specific plugins */ + static plugin_feature_t features[] = { + PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), + PLUGIN_PROVIDE(NONCE_GEN), + PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), + PLUGIN_PROVIDE(DH, MODP_3072_BIT), + PLUGIN_PROVIDE(DH, MODP_4096_BIT), + PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + }; + lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, + countof(features), TRUE); + + fail_if(!charon->initialize(charon, PLUGINS), "Unable to init charon"); + + tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT); + fail_if(!dh, "Unable to create DH object"); + proposal_t *proposal = proposal_create_from_string(PROTO_ESP, + "aes256-sha512-modp4096"); + fail_if(!proposal, "Unable to create proposal"); + proposal->set_spi(proposal, 42); + + tkm_keymat_t *keymat = tkm_keymat_create(TRUE); + fail_if(!keymat, "Unable to create keymat"); + + chunk_t encr_i, encr_r, integ_i, integ_r; + chunk_t nonce = chunk_from_chars("test chunk"); + + fail_unless(keymat->derive_child_keys(keymat, proposal, (diffie_hellman_t *)dh, nonce, nonce, + &encr_i, &integ_i, &encr_r, &integ_r), + "Child key derivation failed"); + + esa_info_t *info = (esa_info_t *)encr_i.ptr; + fail_if(!info, "encr_i does not contain esa information"); + fail_if(info->isa_id != keymat->get_isa_id(keymat), + "Isa context id mismatch (encr_i)"); + fail_if(info->spi_r != 42, + "SPI mismatch (encr_i)"); + fail_unless(chunk_equals(info->nonce_i, nonce), + "nonce_i mismatch (encr_i)"); + fail_unless(chunk_equals(info->nonce_r, nonce), + "nonce_r mismatch (encr_i)"); + fail_if(info->is_encr_r, + "Flag is_encr_r set for encr_i"); + fail_if(info->dh_id != dh->get_id(dh), + "DH context id mismatch (encr_i)"); + chunk_free(&info->nonce_i); + chunk_free(&info->nonce_r); + + info = (esa_info_t *)encr_r.ptr; + fail_if(!info, "encr_r does not contain esa information"); + fail_if(info->isa_id != keymat->get_isa_id(keymat), + "Isa context id mismatch (encr_r)"); + fail_if(info->spi_r != 42, + "SPI mismatch (encr_r)"); + fail_unless(chunk_equals(info->nonce_i, nonce), + "nonce_i mismatch (encr_r)"); + fail_unless(chunk_equals(info->nonce_r, nonce), + "nonce_r mismatch (encr_r)"); + fail_unless(info->is_encr_r, + "Flag is_encr_r set for encr_r"); + fail_if(info->dh_id != dh->get_id(dh), + "DH context id mismatch (encr_i)"); + chunk_free(&info->nonce_i); + chunk_free(&info->nonce_r); + + proposal->destroy(proposal); + dh->dh.destroy(&dh->dh); + keymat->keymat.destroy(&keymat->keymat); + chunk_free(&encr_i); + chunk_free(&encr_r); + + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); +} +END_TEST + TCase *make_keymat_tests(void) { TCase *tc = tcase_create("Keymat tests"); tcase_add_test(tc, test_derive_ike_keys); + tcase_add_test(tc, test_derive_child_keys); return tc; } -- cgit v1.2.3 From 2ac988bf4bbd24ef58aad789ab9bcc82dd66633b Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 18 Sep 2012 15:21:08 +0200 Subject: Implement IKE SA rekeying Use the TKM ike_isa_create_child exchange to rekey an IKE SA. The isa context id is passed on (ab)using the rekey_skd chunk. --- src/charon-tkm/src/tkm/tkm_keymat.c | 38 ++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index f9fd57ae0..9783724e2 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -230,15 +230,36 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, spi_rem = id->get_initiator_spi(id); } + result_type res; key_type sk_ai, sk_ar, sk_ei, sk_er; - DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " - "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); - /* Fake some data for now */ - if (ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, dh_id, nc_id, - nonce_rem, 1, spi_loc, spi_rem, - &sk_ai, &sk_ar, &sk_ei, &sk_er) != TKM_OK) + if (rekey_function == PRF_UNDEFINED) { - DBG1(DBG_IKE, "key derivation failed"); + DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " + "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); + res = ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, dh_id, nc_id, + nonce_rem, this->initiator, spi_loc, spi_rem, + &sk_ai, &sk_ar, &sk_ei, &sk_er); + } + else + { + if (rekey_skd.ptr == NULL || rekey_skd.len != sizeof(isa_id_type)) + { + DBG1(DBG_IKE, "unable to retrieve parent isa context id"); + return FALSE; + } + const isa_id_type parent_isa_id = *((isa_id_type *)(rekey_skd.ptr)); + DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, nc: %llu, dh: %llu," + "spi_loc: %llx, spi_rem: %llx)", parent_isa_id, nc_id, dh_id, + spi_loc, spi_rem); + res = ike_isa_create_child(this->isa_ctx_id, parent_isa_id, 1, dh_id, + nc_id, nonce_rem, this->initiator, spi_loc, + spi_rem, &sk_ai, &sk_ar, &sk_ei, &sk_er); + chunk_free(&rekey_skd); + } + + if (res != TKM_OK) + { + DBG1(DBG_IKE, "key derivation failed (isa: %llu)", this->isa_ctx_id); return FALSE; } @@ -336,8 +357,7 @@ METHOD(tkm_keymat_t, get_auth_octets, bool, METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t, private_tkm_keymat_t *this, chunk_t *skd) { - DBG1(DBG_IKE, "returning skd"); - *skd = chunk_empty; + *skd = chunk_clone(chunk_from_thing(this->isa_ctx_id)); return PRF_HMAC_SHA2_512; } -- cgit v1.2.3 From 62b625430eba1ec2b3eb970e32b90ce0c1b956c0 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 18 Sep 2012 19:01:38 +0200 Subject: Let tkm_keymat_t extend keymat_v2_t --- src/charon-tkm/src/tkm/tkm_keymat.c | 34 +++++++-------- src/charon-tkm/src/tkm/tkm_keymat.h | 82 ++----------------------------------- src/charon-tkm/tests/keymat_tests.c | 17 ++++---- 3 files changed, 31 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 9783724e2..9f3faf536 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -164,7 +164,7 @@ METHOD(keymat_t, create_nonce_gen, nonce_gen_t*, return lib->crypto->create_nonce_gen(lib->crypto); } -METHOD(tkm_keymat_t, derive_ike_keys, bool, +METHOD(keymat_v2_t, derive_ike_keys, bool, private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) @@ -296,7 +296,7 @@ METHOD(tkm_keymat_t, derive_ike_keys, bool, return TRUE; } -METHOD(tkm_keymat_t, derive_child_keys, bool, +METHOD(keymat_v2_t, derive_child_keys, bool, private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r) @@ -345,7 +345,7 @@ METHOD(keymat_t, get_aead, aead_t*, return in ? this->aead_in : this->aead_out; } -METHOD(tkm_keymat_t, get_auth_octets, bool, +METHOD(keymat_v2_t, get_auth_octets, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) { @@ -354,14 +354,14 @@ METHOD(tkm_keymat_t, get_auth_octets, bool, return TRUE; } -METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t, +METHOD(keymat_v2_t, get_skd, pseudo_random_function_t, private_tkm_keymat_t *this, chunk_t *skd) { *skd = chunk_clone(chunk_from_thing(this->isa_ctx_id)); return PRF_HMAC_SHA2_512; } -METHOD(tkm_keymat_t, get_psk_sig, bool, +METHOD(keymat_v2_t, get_psk_sig, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) { @@ -432,18 +432,20 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) INIT(this, .public = { - .keymat = { - .get_version = _get_version, - .create_dh = _create_dh, - .create_nonce_gen = _create_nonce_gen, - .get_aead = _get_aead, - .destroy = _destroy, + .keymat_v2 = { + .keymat = { + .get_version = _get_version, + .create_dh = _create_dh, + .create_nonce_gen = _create_nonce_gen, + .get_aead = _get_aead, + .destroy = _destroy, + }, + .derive_ike_keys = _derive_ike_keys, + .derive_child_keys = _derive_child_keys, + .get_skd = _get_skd, + .get_auth_octets = _get_auth_octets, + .get_psk_sig = _get_psk_sig, }, - .derive_ike_keys = _derive_ike_keys, - .derive_child_keys = _derive_child_keys, - .get_skd = _get_skd, - .get_auth_octets = _get_auth_octets, - .get_psk_sig = _get_psk_sig, .get_isa_id = _get_isa_id, .set_auth_payload = _set_auth_payload, .get_auth_payload = _get_auth_payload, diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index 22da32f4e..16f2f2a49 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -17,7 +17,7 @@ #ifndef TKM_KEYMAT_H_ #define TKM_KEYMAT_H_ -#include +#include typedef struct tkm_keymat_t tkm_keymat_t; @@ -27,85 +27,9 @@ typedef struct tkm_keymat_t tkm_keymat_t; struct tkm_keymat_t { /** - * Implements keymat_t. + * Implements keymat_v2_t. */ - keymat_t keymat; - - /** - * Use TKM to derive IKE key material. - * - * @param proposal selected algorithms - * @param dh diffie hellman key allocated by create_dh() - * @param nonce_i initiators nonce value - * @param nonce_r responders nonce value - * @param id IKE_SA identifier - * @param rekey_prf PRF of old SA if rekeying, PRF_UNDEFINED otherwise - * @param rekey_skd SKd of old SA if rekeying - * @return TRUE on success - */ - bool (*derive_ike_keys)(tkm_keymat_t *this, proposal_t *proposal, - diffie_hellman_t *dh, chunk_t nonce_i, - chunk_t nonce_r, ike_sa_id_t *id, - pseudo_random_function_t rekey_function, - chunk_t rekey_skd); - - /** - * Use TKM to derive child key material. - * - * @param proposal selected algorithms - * @param dh diffie hellman key allocated by create_dh(), or NULL - * @param nonce_i initiators nonce value - * @param nonce_r responders nonce value - * @param encr_i handle to initiators encryption key - * @param integ_i handle to initiators integrity key - * @param encr_r handle to responders encryption key - * @param integ_r handle to responders integrity key - * @return TRUE on success - */ - bool (*derive_child_keys)(tkm_keymat_t *this, - proposal_t *proposal, diffie_hellman_t *dh, - chunk_t nonce_i, chunk_t nonce_r, - chunk_t *encr_i, chunk_t *integ_i, - chunk_t *encr_r, chunk_t *integ_r); - - /** - * Use TKM to generate auth octets. - * - * @param verify TRUE to create for verfification, FALSE to sign - * @param ike_sa_init encoded ike_sa_init message - * @param nonce nonce value - * @param id identity - * @param reserved reserved bytes of id_payload - * @param octests chunk receiving allocated auth octets - * @return TRUE if octets created successfully - */ - bool (*get_auth_octets)(tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, identification_t *id, - char reserved[3], chunk_t *octets); - - /** - * Get SKd and PRF to derive keymat. - * - * @param skd chunk to write SKd to (internal data) - * @return PRF function to derive keymat - */ - pseudo_random_function_t (*get_skd)(tkm_keymat_t *this, chunk_t *skd); - - /** - * Build the shared secret signature used for PSK and EAP authentication. - * - * @param verify TRUE to create for verfification, FALSE to sign - * @param ike_sa_init encoded ike_sa_init message - * @param nonce nonce value - * @param secret optional secret to include into signature - * @param id identity - * @param reserved reserved bytes of id_payload - * @param sign chunk receiving allocated signature octets - * @return TRUE if signature created successfully - */ - bool (*get_psk_sig)(tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, chunk_t secret, - identification_t *id, char reserved[3], chunk_t *sig); + keymat_v2_t keymat_v2; /** * Get ISA context id. diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index 3e01e99f1..e4c59fa64 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -79,11 +79,12 @@ START_TEST(test_derive_ike_keys) dh->dh.get_my_public_value(&dh->dh, &pubvalue); dh->dh.set_other_public_value(&dh->dh, pubvalue); - fail_unless(keymat->derive_ike_keys(keymat, proposal, &dh->dh, nonce, nonce, - ike_sa_id, PRF_UNDEFINED, chunk_empty), "Key derivation failed"); + fail_unless(keymat->keymat_v2.derive_ike_keys(&keymat->keymat_v2, proposal, + &dh->dh, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty), + "Key derivation failed"); chunk_free(&nonce); - aead_t * const aead = keymat->keymat.get_aead(&keymat->keymat, TRUE); + aead_t * const aead = keymat->keymat_v2.keymat.get_aead(&keymat->keymat_v2.keymat, TRUE); fail_if(!aead, "AEAD is NULL"); fail_if(aead->get_key_size(aead) != 96, "Key size mismatch %d", @@ -94,7 +95,7 @@ START_TEST(test_derive_ike_keys) proposal->destroy(proposal); dh->dh.destroy(&dh->dh); ike_sa_id->destroy(ike_sa_id); - keymat->keymat.destroy(&keymat->keymat); + keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); chunk_free(&pubvalue); libcharon_deinit(); @@ -140,8 +141,10 @@ START_TEST(test_derive_child_keys) chunk_t encr_i, encr_r, integ_i, integ_r; chunk_t nonce = chunk_from_chars("test chunk"); - fail_unless(keymat->derive_child_keys(keymat, proposal, (diffie_hellman_t *)dh, nonce, nonce, - &encr_i, &integ_i, &encr_r, &integ_r), + fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal, + (diffie_hellman_t *)dh, + nonce, nonce, &encr_i, + &integ_i, &encr_r, &integ_r), "Child key derivation failed"); esa_info_t *info = (esa_info_t *)encr_i.ptr; @@ -180,7 +183,7 @@ START_TEST(test_derive_child_keys) proposal->destroy(proposal); dh->dh.destroy(&dh->dh); - keymat->keymat.destroy(&keymat->keymat); + keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); chunk_free(&encr_i); chunk_free(&encr_r); -- cgit v1.2.3 From d9c648068859f17271d0880100d1845206cbd4ab Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 19 Sep 2012 17:55:28 +0200 Subject: Conditionally reset AE context in keymat destroy The responsibility to reset an authenticated endpoint context is passed from a parent IKE SA keymat to the new keymat by including it in the ISA info data contained in the skd chunk. The last IKE SA to be destroyed will also reset the associated AE context. --- src/charon-tkm/src/tkm/tkm_keymat.c | 54 ++++++++++++++++++++++++++++--------- src/charon-tkm/src/tkm/tkm_types.h | 24 +++++++++++++++++ 2 files changed, 66 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 9f3faf536..c310d2200 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -234,6 +234,12 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, key_type sk_ai, sk_ar, sk_ei, sk_er; if (rekey_function == PRF_UNDEFINED) { + this->ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE); + if (!this->ae_ctx_id) + { + DBG1(DBG_IKE, "unable to acquire ae context id"); + return FALSE; + } DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, " "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem); res = ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, dh_id, nc_id, @@ -242,18 +248,20 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, } else { - if (rekey_skd.ptr == NULL || rekey_skd.len != sizeof(isa_id_type)) + if (rekey_skd.ptr == NULL || rekey_skd.len != sizeof(isa_info_t)) { - DBG1(DBG_IKE, "unable to retrieve parent isa context id"); + DBG1(DBG_IKE, "unable to retrieve parent isa info"); return FALSE; } - const isa_id_type parent_isa_id = *((isa_id_type *)(rekey_skd.ptr)); - DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, nc: %llu, dh: %llu," - "spi_loc: %llx, spi_rem: %llx)", parent_isa_id, nc_id, dh_id, - spi_loc, spi_rem); - res = ike_isa_create_child(this->isa_ctx_id, parent_isa_id, 1, dh_id, - nc_id, nonce_rem, this->initiator, spi_loc, - spi_rem, &sk_ai, &sk_ar, &sk_ei, &sk_er); + const isa_info_t isa_info = *((isa_info_t *)(rekey_skd.ptr)); + DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, nc: %llu," + "dh: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, + isa_info.ae_id, nc_id, dh_id, spi_loc, spi_rem); + this->ae_ctx_id = isa_info.ae_id; + res = ike_isa_create_child(this->isa_ctx_id, isa_info.parent_isa_id, 1, + dh_id, nc_id, nonce_rem, this->initiator, + spi_loc, spi_rem, &sk_ai, &sk_ar, &sk_ei, + &sk_er); chunk_free(&rekey_skd); } @@ -357,7 +365,20 @@ METHOD(keymat_v2_t, get_auth_octets, bool, METHOD(keymat_v2_t, get_skd, pseudo_random_function_t, private_tkm_keymat_t *this, chunk_t *skd) { - *skd = chunk_clone(chunk_from_thing(this->isa_ctx_id)); + isa_info_t *isa_info; + + INIT(isa_info, + .parent_isa_id = this->isa_ctx_id, + .ae_id = this->ae_ctx_id, + ); + + *skd = chunk_create((u_char *)isa_info, sizeof(isa_info_t)); + + /* + * remove ae context id, since control has now been handed over to the new + * IKE SA keymat + */ + this->ae_ctx_id = 0; return PRF_HMAC_SHA2_512; } @@ -398,6 +419,15 @@ METHOD(keymat_t, destroy, void, DBG1(DBG_IKE, "failed to reset ISA context %d", this->isa_ctx_id); } tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ISA, this->isa_ctx_id); + /* only reset ae context if set */ + if (this->ae_ctx_id != 0) + { + if (ike_ae_reset(this->ae_ctx_id) != TKM_OK) + { + DBG1(DBG_IKE, "failed to reset AE context %d", this->ae_ctx_id); + } + tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_AE, this->ae_ctx_id); + } DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); @@ -452,11 +482,11 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) }, .initiator = initiator, .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), - .ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE), + .ae_ctx_id = 0, .auth_payload = chunk_empty, ); - if (!this->isa_ctx_id || !this->ae_ctx_id) + if (!this->isa_ctx_id) { free(this); return NULL; diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index 65f45cf68..28c4d9948 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -70,4 +70,28 @@ struct esa_info_t { }; +typedef struct isa_info_t isa_info_t; + +/** + * IKE SA info data structure. + * This type is used to transfer ISA information from the keymat of the parent + * SA to the keymat of the new IKE SA. For this purpose the skd data chunk is + * (ab)used. This is possible since the sk_d chunk is treated as an opaque value + * and handed to the derive_ike_keys procedure of the new keymat as-is without + * any processing. + */ +struct isa_info_t { + + /** + * Parent isa context id. + */ + isa_id_type parent_isa_id; + + /** + * Authenticated endpoint context id. + */ + ae_id_type ae_id; + +}; + #endif /** TKM_TYPES_H_ */ -- cgit v1.2.3 From e0cb01f44d81a9971e06a04e7d3d45eabc9b5dc1 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 26 Sep 2012 15:40:27 +0200 Subject: Implement Esa Event Service (EES) The Esa Event Service can be used to trigger ESP SA (ESA) events such as acquire or expire. The incoming events are forwarded to the hydra kernel interface for processing. --- src/charon-tkm/Makefile.am | 1 + src/charon-tkm/build_charon.gpr | 3 +- src/charon-tkm/build_common.gpr | 16 ++++++- src/charon-tkm/build_tests.gpr | 6 +-- src/charon-tkm/src/ees/ees_callbacks.c | 40 +++++++++++++++++ src/charon-tkm/src/ees/ees_callbacks.h | 32 +++++++++++++ src/charon-tkm/src/ees/esa_event_service.adb | 65 +++++++++++++++++++++++++++ src/charon-tkm/src/ees/esa_event_service.ads | 35 +++++++++++++++ src/charon-tkm/src/ees/tkmrpc-servers-ees.adb | 65 +++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm.c | 16 ++++++- 10 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 src/charon-tkm/src/ees/ees_callbacks.c create mode 100644 src/charon-tkm/src/ees/ees_callbacks.h create mode 100644 src/charon-tkm/src/ees/esa_event_service.adb create mode 100644 src/charon-tkm/src/ees/esa_event_service.ads create mode 100644 src/charon-tkm/src/ees/tkmrpc-servers-ees.adb (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 6c7359323..10e161dcf 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -17,6 +17,7 @@ LIBFL = -lstrongswan -lhydra -lcharon DEFS += -DPLUGINS=\""$(PLUGINS)\"" -DIPSEC_PIDDIR=\"${piddir}\" BUILD_OPTS = \ + -XOBJ_DIR=$(CURDIR)/obj \ -cargs $(INCLUDES) $(DEFS) \ -largs $(LIBLD) $(LIBFL) diff --git a/src/charon-tkm/build_charon.gpr b/src/charon-tkm/build_charon.gpr index c162376a8..bf6880668 100644 --- a/src/charon-tkm/build_charon.gpr +++ b/src/charon-tkm/build_charon.gpr @@ -2,12 +2,13 @@ with "build_common"; project Build_Charon is - for Languages use ("C"); + for Languages use ("Ada", "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 ("ada") use Build_Common.Ada_Compiler_Switches; for Default_Switches ("c") use Build_Common.C_Compiler_Switches & "-Werror"; end Compiler; diff --git a/src/charon-tkm/build_common.gpr b/src/charon-tkm/build_common.gpr index d742692ef..e32832a28 100644 --- a/src/charon-tkm/build_common.gpr +++ b/src/charon-tkm/build_common.gpr @@ -1,10 +1,22 @@ with "tkmrpc_client"; +with "tkmrpc_server-ees"; project Build_Common is for Source_Dirs use (); - Obj_Dir := "obj"; - Compiler_Switches := ("-W", "-Wall", "-Wno-unused-parameter"); + Obj_Dir := "obj"; + C_Compiler_Switches := ("-W", + "-Wall", + "-Wno-unused-parameter"); + Ada_Compiler_Switches := ("-gnatwale", + "-gnatygAdISuxo", + "-gnata", + "-gnatVa", + "-gnat05", + "-gnatf", + "-fstack-check", + "-gnato", + "-g"); end Build_Common; diff --git a/src/charon-tkm/build_tests.gpr b/src/charon-tkm/build_tests.gpr index 35f0c9bdd..7aa07003a 100644 --- a/src/charon-tkm/build_tests.gpr +++ b/src/charon-tkm/build_tests.gpr @@ -2,13 +2,13 @@ with "build_common"; project Build_Tests is - for Languages use ("C"); - for Source_Dirs use ("src/tkm", "tests"); + for Languages use ("Ada", "C"); + for Source_Dirs use ("src/tkm", "src/ees", "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; + for Default_Switches ("c") use Build_Common.C_Compiler_Switches; end Compiler; end Build_Tests; diff --git a/src/charon-tkm/src/ees/ees_callbacks.c b/src/charon-tkm/src/ees/ees_callbacks.c new file mode 100644 index 000000000..2d9653837 --- /dev/null +++ b/src/charon-tkm/src/ees/ees_callbacks.c @@ -0,0 +1,40 @@ +/* + * 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 . + * + * 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 +#include +#include +#include + +#include "ees_callbacks.h" + +void charon_esa_acquire(result_type *res, const sp_id_type sp_id) +{ + DBG1(DBG_KNL, "ees: acquire received for reqid {%d}", sp_id); + hydra->kernel_interface->acquire(hydra->kernel_interface, sp_id, NULL, + NULL); + *res = TKM_OK; +} + +void charon_esa_expire(result_type *res, const sp_id_type sp_id, + const esp_spi_type spi_rem, const protocol_type protocol, + const expiry_flag_type hard) +{ + DBG1(DBG_KNL, "ees: expire received for reqid {%d}", sp_id); + hydra->kernel_interface->expire(hydra->kernel_interface, sp_id, protocol, + spi_rem, hard != 0); + *res = TKM_OK; +} diff --git a/src/charon-tkm/src/ees/ees_callbacks.h b/src/charon-tkm/src/ees/ees_callbacks.h new file mode 100644 index 000000000..f8598f238 --- /dev/null +++ b/src/charon-tkm/src/ees/ees_callbacks.h @@ -0,0 +1,32 @@ +/* + * 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 . + * + * 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 EES_CALLBACKS_H_ +#define EES_CALLBACKS_H_ + +/** + * Process Acquire event for given security policy. + */ +void charon_esa_acquire(result_type *res, const sp_id_type sp_id); + +/** + * Process Expire event for given security policy. + */ +void charon_esa_expire(result_type *res, const sp_id_type sp_id, + const esp_spi_type spi_rem, const protocol_type protocol, + const expiry_flag_type hard); + +#endif /** EES_CALLBACKS_H_ */ diff --git a/src/charon-tkm/src/ees/esa_event_service.adb b/src/charon-tkm/src/ees/esa_event_service.adb new file mode 100644 index 000000000..7b35090af --- /dev/null +++ b/src/charon-tkm/src/ees/esa_event_service.adb @@ -0,0 +1,65 @@ +-- +-- 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 . +-- +-- 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. +-- + +with Anet.Sockets.Unix; +with Anet.Receivers.Stream; + +with Tkmrpc.Dispatchers.Ees; +with Tkmrpc.Process_Stream; + +pragma Elaborate_All (Anet.Receivers.Stream); +pragma Elaborate_All (Tkmrpc.Process_Stream); + +package body Esa_Event_Service +is + + package Unix_TCP_Receiver is new Anet.Receivers.Stream + (Socket_Type => Anet.Sockets.Unix.TCP_Socket_Type); + + procedure Dispatch is new Tkmrpc.Process_Stream + (Dispatch => Tkmrpc.Dispatchers.Ees.Dispatch); + + Sock : aliased Anet.Sockets.Unix.TCP_Socket_Type; + Receiver : Unix_TCP_Receiver.Receiver_Type (S => Sock'Access); + + ------------------------------------------------------------------------- + + procedure Finalize + is + begin + Receiver.Stop; + end Finalize; + + ------------------------------------------------------------------------- + + procedure Init + (Result : out Tkmrpc.Results.Result_Type; + Address : Interfaces.C.Strings.chars_ptr) + is + Path : constant String := Interfaces.C.Strings.Value (Address); + begin + Sock.Init; + Sock.Bind (Path => Anet.Sockets.Unix.Path_Type (Path)); + Receiver.Listen (Callback => Dispatch'Access); + + Result := Tkmrpc.Results.Ok; + + exception + when others => + Result := Tkmrpc.Results.Invalid_Operation; + end Init; + +end Esa_Event_Service; diff --git a/src/charon-tkm/src/ees/esa_event_service.ads b/src/charon-tkm/src/ees/esa_event_service.ads new file mode 100644 index 000000000..5ead0ca0c --- /dev/null +++ b/src/charon-tkm/src/ees/esa_event_service.ads @@ -0,0 +1,35 @@ +-- +-- 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 . +-- +-- 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. +-- + +with Interfaces.C.Strings; + +with Tkmrpc.Results; + +package Esa_Event_Service +is + + procedure Init + (Result : out Tkmrpc.Results.Result_Type; + Address : Interfaces.C.Strings.chars_ptr); + pragma Export (C, Init, "ees_server_init"); + pragma Export_Valued_Procedure (Init); + -- Initialize Esa Event Service (EES) with given address. + + procedure Finalize; + pragma Export (C, Finalize, "ees_server_finalize"); + -- Finalize EES. + +end Esa_Event_Service; diff --git a/src/charon-tkm/src/ees/tkmrpc-servers-ees.adb b/src/charon-tkm/src/ees/tkmrpc-servers-ees.adb new file mode 100644 index 000000000..2240065c2 --- /dev/null +++ b/src/charon-tkm/src/ees/tkmrpc-servers-ees.adb @@ -0,0 +1,65 @@ +package body Tkmrpc.Servers.Ees +is + + -------------------------------- + -- charon callback signatures -- + -------------------------------- + + procedure Charon_Esa_Acquire + (Result : out Results.Result_Type; + Sp_Id : Types.Sp_Id_Type); + pragma Import (C, Charon_Esa_Acquire, "charon_esa_acquire"); + + procedure Charon_Esa_Expire + (Result : out Results.Result_Type; + Sp_Id : Types.Sp_Id_Type; + Spi_Rem : Types.Esp_Spi_Type; + Protocol : Types.Protocol_Type; + Hard : Types.Expiry_Flag_Type); + pragma Import (C, Charon_Esa_Expire, "charon_esa_expire"); + + ------------------------------------------------------------------------- + + procedure Esa_Acquire + (Result : out Results.Result_Type; + Sp_Id : Types.Sp_Id_Type) + is + begin + Charon_Esa_Acquire (Result => Result, + Sp_Id => Sp_Id); + end Esa_Acquire; + + ------------------------------------------------------------------------- + + procedure Esa_Expire + (Result : out Results.Result_Type; + Sp_Id : Types.Sp_Id_Type; + Spi_Rem : Types.Esp_Spi_Type; + Protocol : Types.Protocol_Type; + Hard : Types.Expiry_Flag_Type) + is + begin + Charon_Esa_Expire (Result => Result, + Sp_Id => Sp_Id, + Spi_Rem => Spi_Rem, + Protocol => Protocol, + Hard => Hard); + end Esa_Expire; + + ------------------------------------------------------------------------- + + procedure Finalize + is + begin + null; + end Finalize; + + ------------------------------------------------------------------------- + + procedure Init + is + begin + null; + end Init; + +end Tkmrpc.Servers.Ees; diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 5fc554e13..cdd4f4ad7 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -20,10 +20,14 @@ #include "tkm.h" #define IKE_SOCKET "/tmp/tkm.rpc.ike" +#define EES_SOCKET "/tmp/tkm.rpc.ees" typedef struct private_tkm_t private_tkm_t; -/** +extern result_type ees_server_init(const char * const address); +extern void ees_server_finalize(void); + +/* * Private additions to tkm_t. */ struct private_tkm_t { @@ -61,9 +65,16 @@ bool tkm_init() tkmlib_final(); return FALSE; } + /* init esa event service */ + if (ees_server_init(EES_SOCKET) != TKM_OK) + { + tkmlib_final(); + return FALSE; + } if (ike_tkm_reset() != TKM_OK) { + ees_server_finalize(); tkmlib_final(); return FALSE; } @@ -71,6 +82,7 @@ bool tkm_init() /* get limits from tkm */ if (ike_tkm_limits(&max_requests, &nc, &dh, &cc, &ae, &isa, &esa) != TKM_OK) { + ees_server_finalize(); tkmlib_final(); return FALSE; } @@ -101,6 +113,8 @@ void tkm_deinit() this->public.idmgr->destroy(this->public.idmgr); this->public.chunk_map->destroy(this->public.chunk_map); + ees_server_finalize(); + tkmlib_final(); free(this); tkm = NULL; -- cgit v1.2.3 From 270b321e977d09cb1d2eb8dbf07783e0b258995c Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 2 Oct 2012 17:03:39 +0200 Subject: Implement Ada exception processing Register a global exception action with the Ada runtime to log uncaught exceptions to the daemon log and terminate. --- src/charon-tkm/build_charon.gpr | 4 ++ src/charon-tkm/build_common.gpr | 3 ++ src/charon-tkm/build_tests.gpr | 2 +- src/charon-tkm/src/ehandler/eh_callbacks.c | 28 +++++++++++ src/charon-tkm/src/ehandler/eh_callbacks.h | 25 ++++++++++ src/charon-tkm/src/ehandler/exception_handler.adb | 57 +++++++++++++++++++++++ src/charon-tkm/src/ehandler/exception_handler.ads | 24 ++++++++++ src/charon-tkm/src/tkm/tkm.c | 4 ++ 8 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/charon-tkm/src/ehandler/eh_callbacks.c create mode 100644 src/charon-tkm/src/ehandler/eh_callbacks.h create mode 100644 src/charon-tkm/src/ehandler/exception_handler.adb create mode 100644 src/charon-tkm/src/ehandler/exception_handler.ads (limited to 'src') diff --git a/src/charon-tkm/build_charon.gpr b/src/charon-tkm/build_charon.gpr index bf6880668..b208667a3 100644 --- a/src/charon-tkm/build_charon.gpr +++ b/src/charon-tkm/build_charon.gpr @@ -13,4 +13,8 @@ project Build_Charon is & "-Werror"; end Compiler; + package Binder is + for Default_Switches ("ada") use Build_Common.Ada_Binder_Switches; + end Binder; + end Build_Charon; diff --git a/src/charon-tkm/build_common.gpr b/src/charon-tkm/build_common.gpr index e32832a28..ac322d713 100644 --- a/src/charon-tkm/build_common.gpr +++ b/src/charon-tkm/build_common.gpr @@ -19,4 +19,7 @@ project Build_Common is "-fstack-check", "-gnato", "-g"); + + Ada_Binder_Switches := ("-E"); + end Build_Common; diff --git a/src/charon-tkm/build_tests.gpr b/src/charon-tkm/build_tests.gpr index 7aa07003a..032c7969e 100644 --- a/src/charon-tkm/build_tests.gpr +++ b/src/charon-tkm/build_tests.gpr @@ -3,7 +3,7 @@ with "build_common"; project Build_Tests is for Languages use ("Ada", "C"); - for Source_Dirs use ("src/tkm", "src/ees", "tests"); + for Source_Dirs use ("src/ees", "src/ehandler", "src/tkm", "tests"); for Main use ("test_runner"); for Object_Dir use Build_Common.Obj_Dir; diff --git a/src/charon-tkm/src/ehandler/eh_callbacks.c b/src/charon-tkm/src/ehandler/eh_callbacks.c new file mode 100644 index 000000000..7dca97c3e --- /dev/null +++ b/src/charon-tkm/src/ehandler/eh_callbacks.c @@ -0,0 +1,28 @@ +/* + * 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 . + * + * 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 +#include +#include + +#include "eh_callbacks.h" + +void charon_terminate(char *msg) +{ + DBG1(DBG_DMN, "critical TKM error, terminating!"); + DBG1(DBG_DMN, msg); + kill(0, SIGTERM); +} diff --git a/src/charon-tkm/src/ehandler/eh_callbacks.h b/src/charon-tkm/src/ehandler/eh_callbacks.h new file mode 100644 index 000000000..1be924913 --- /dev/null +++ b/src/charon-tkm/src/ehandler/eh_callbacks.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 . + * + * 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 EH_CALLBACKS_H_ +#define EH_CALLBACKS_H_ + +/** + * Log given message and terminate charon. + */ +void charon_terminate(char *msg); + +#endif /** EH_CALLBACKS_H_ */ diff --git a/src/charon-tkm/src/ehandler/exception_handler.adb b/src/charon-tkm/src/ehandler/exception_handler.adb new file mode 100644 index 000000000..3f165e1cd --- /dev/null +++ b/src/charon-tkm/src/ehandler/exception_handler.adb @@ -0,0 +1,57 @@ +-- +-- 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 . +-- +-- 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. +-- + +with Ada.Exceptions; + +with GNAT.Exception_Actions; + +with Interfaces.C.Strings; + +package body Exception_Handler +is + + procedure Charon_Terminate (Message : Interfaces.C.Strings.chars_ptr); + pragma Import (C, Charon_Terminate, "charon_terminate"); + + procedure Bailout (Ex : Ada.Exceptions.Exception_Occurrence); + -- Signal critical condition to charon daemon. + + ------------------------------------------------------------------------- + + procedure Bailout (Ex : Ada.Exceptions.Exception_Occurrence) + is + begin + if Ada.Exceptions.Exception_Name (Ex) = "_ABORT_SIGNAL" then + + -- Ignore runtime-internal abort signal exception. + + return; + end if; + + Charon_Terminate (Message => Interfaces.C.Strings.New_String + (Ada.Exceptions.Exception_Information (Ex))); + end Bailout; + + ------------------------------------------------------------------------- + + procedure Init + is + begin + GNAT.Exception_Actions.Register_Global_Action + (Action => Bailout'Access); + end Init; + +end Exception_Handler; diff --git a/src/charon-tkm/src/ehandler/exception_handler.ads b/src/charon-tkm/src/ehandler/exception_handler.ads new file mode 100644 index 000000000..29dd3d8f4 --- /dev/null +++ b/src/charon-tkm/src/ehandler/exception_handler.ads @@ -0,0 +1,24 @@ +-- +-- 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 . +-- +-- 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. +-- + +package Exception_Handler +is + + procedure Init; + pragma Export (C, Init, "ehandler_init"); + -- Register last-chance exception handler. + +end Exception_Handler; diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index cdd4f4ad7..6e27586ed 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -26,6 +26,7 @@ typedef struct private_tkm_t private_tkm_t; extern result_type ees_server_init(const char * const address); extern void ees_server_finalize(void); +extern void ehandler_init(void); /* * Private additions to tkm_t. @@ -60,6 +61,9 @@ bool tkm_init() /* initialize TKM client library */ tkmlib_init(); + + ehandler_init(); + if (ike_init(IKE_SOCKET) != TKM_OK) { tkmlib_final(); -- cgit v1.2.3 From 0f0165c81f1b33279ad2d10e3b9a8a955d2bf55b Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Thu, 4 Oct 2012 11:17:33 +0200 Subject: Add typelen parameter to chunk_to_sequence function The parameter is used to initialize the given sequence to zero. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 4 ++-- src/charon-tkm/src/tkm/tkm_keymat.c | 8 ++++---- src/charon-tkm/src/tkm/tkm_listener.c | 2 +- src/charon-tkm/src/tkm/tkm_utils.c | 4 +++- src/charon-tkm/src/tkm/tkm_utils.h | 4 +++- src/charon-tkm/tests/utils_tests.c | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 95b378fde..4e813a035 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -145,7 +145,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, else if (nonce_loc_id != 0 && esa.dh_id == 0) { nonce_type nc_rem; - chunk_to_sequence(nonce_rem, &nc_rem); + chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create_no_pfs(esa_id, esa.isa_id, 1, 1, nonce_loc_id, nc_rem, initiator, ntohl(spi_loc), ntohl(spi_rem)) != TKM_OK) @@ -159,7 +159,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, else { nonce_type nc_rem; - chunk_to_sequence(nonce_rem, &nc_rem); + chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create(esa_id, esa.isa_id, 1, 1, esa.dh_id, nonce_loc_id, nc_rem, initiator, ntohl(spi_loc), ntohl(spi_rem)) != TKM_OK) diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index c310d2200..9beb10430 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -219,13 +219,13 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, if (this->initiator) { - chunk_to_sequence(&nonce_r, &nonce_rem); + chunk_to_sequence(&nonce_r, &nonce_rem, sizeof(nonce_type)); spi_loc = id->get_initiator_spi(id); spi_rem = id->get_responder_spi(id); } else { - chunk_to_sequence(&nonce_i, &nonce_rem); + chunk_to_sequence(&nonce_i, &nonce_rem, sizeof(nonce_type)); spi_loc = id->get_responder_spi(id); spi_rem = id->get_initiator_spi(id); } @@ -390,14 +390,14 @@ METHOD(keymat_v2_t, get_psk_sig, bool, signature_type signature; init_message_type msg; - chunk_to_sequence(&ike_sa_init, &msg); + chunk_to_sequence(&ike_sa_init, &msg, sizeof(init_message_type)); chunk_t idx_chunk, chunk = chunk_alloca(4); chunk.ptr[0] = id->get_type(id); memcpy(chunk.ptr + 1, reserved, 3); idx_chunk = chunk_cata("cc", chunk, id->get_encoding(id)); idx_type idx; - chunk_to_sequence(&idx_chunk, &idx); + chunk_to_sequence(&idx_chunk, &idx, sizeof(idx_type)); if (ike_isa_sign_psk(this->isa_ctx_id, msg, idx, verify == TRUE, &signature) != TKM_OK) diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 557b276b8..8bf92f4e7 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -60,7 +60,7 @@ METHOD(listener_t, authorize, bool, } signature_type signature; - chunk_to_sequence(auth, &signature); + chunk_to_sequence(auth, &signature, sizeof(signature_type)); if (ike_isa_auth_psk(isa_id, signature) != TKM_OK) { DBG1(DBG_IKE, "TKM based authentication failed" diff --git a/src/charon-tkm/src/tkm/tkm_utils.c b/src/charon-tkm/src/tkm/tkm_utils.c index e60db5906..28fcdd1d1 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.c +++ b/src/charon-tkm/src/tkm/tkm_utils.c @@ -30,8 +30,10 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, memcpy(chunk->ptr, first, len); } -void chunk_to_sequence(const chunk_t * const chunk, void *sequence) +void chunk_to_sequence(const chunk_t * const chunk, void *sequence, + const uint32_t typelen) { + memset(sequence, 0, typelen); sequence_type *seq = sequence; seq->size = chunk->len; memcpy(seq->data, chunk->ptr, seq->size); diff --git a/src/charon-tkm/src/tkm/tkm_utils.h b/src/charon-tkm/src/tkm/tkm_utils.h index c78ffd549..37a2c7ce5 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.h +++ b/src/charon-tkm/src/tkm/tkm_utils.h @@ -35,7 +35,9 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, * * @param chunk pointer to chunk struct * @param sequence pointer to variable-length sequence + * @param typelen length of sequence type */ -void chunk_to_sequence(const chunk_t * const chunk, void *sequence); +void chunk_to_sequence(const chunk_t * const chunk, void *sequence, + const uint32_t typelen); #endif /** TKM_UTILS_H_ */ diff --git a/src/charon-tkm/tests/utils_tests.c b/src/charon-tkm/tests/utils_tests.c index acc93ecf9..b3ead7633 100644 --- a/src/charon-tkm/tests/utils_tests.c +++ b/src/charon-tkm/tests/utils_tests.c @@ -41,7 +41,7 @@ START_TEST(test_chunk_to_sequence) chunk_t chunk = chunk_from_thing("ABCDEFGH"); key_type key; - chunk_to_sequence(&chunk, &key); + chunk_to_sequence(&chunk, &key, sizeof(key_type)); fail_if(key.size != chunk.len, "Seq size mismatch"); uint32_t i; -- cgit v1.2.3 From 464eb54ba4c425ff6aa61fb5944583a2e1f12c3a Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 25 Sep 2012 17:13:19 +0200 Subject: Add TKM_CTX_CC (Certificate chain context id) --- src/charon-tkm/src/tkm/tkm.c | 2 +- src/charon-tkm/src/tkm/tkm_id_manager.c | 1 + src/charon-tkm/src/tkm/tkm_id_manager.h | 2 ++ src/charon-tkm/tests/id_manager_tests.c | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 6e27586ed..ce4cedcbc 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -91,7 +91,7 @@ bool tkm_init() return FALSE; } - const tkm_limits_t limits = {nc, dh, isa, ae, esa}; + const tkm_limits_t limits = {nc, dh, cc, isa, ae, esa}; INIT(this, .public = { diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 24513ebf1..63377e65d 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -25,6 +25,7 @@ ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ESA, "NONCE_CONTEXT", "DH_CONTEXT", + "CC_CONTEXT" "ISA_CONTEXT", "AE_CONTEXT", "ESA_CONTEXT"); diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index 716e91d79..b1c1160a0 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -30,6 +30,8 @@ enum tkm_context_kind_t { TKM_CTX_NONCE, /** Diffie-Hellman context */ TKM_CTX_DH, + /** Certificate chain context */ + TKM_CTX_CC, /** IKE SA context */ TKM_CTX_ISA, /** Authenticated Endpoint context */ diff --git a/src/charon-tkm/tests/id_manager_tests.c b/src/charon-tkm/tests/id_manager_tests.c index fd34bf91f..15522f118 100644 --- a/src/charon-tkm/tests/id_manager_tests.c +++ b/src/charon-tkm/tests/id_manager_tests.c @@ -18,7 +18,7 @@ #include "tkm_id_manager.h" -static const tkm_limits_t limits = {125, 100, 30, 200, 42}; +static const tkm_limits_t limits = {125, 100, 55, 30, 200, 42}; START_TEST(test_id_mgr_creation) { -- cgit v1.2.3 From 351bd59de26ef94fac418e730329815021cfd062 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 25 Sep 2012 15:21:11 +0200 Subject: Build cc context in tkm listener authorize hook Extract peer certificate information and build a TKM certificate chain context in the authorize hook of the tkm_listener_t. The cc context will be used for ISA authentication using certificates. --- src/charon-tkm/src/tkm/tkm_listener.c | 143 ++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 8bf92f4e7..5820990f4 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -21,6 +21,7 @@ #include #include +#include "tkm.h" #include "tkm_listener.h" #include "tkm_keymat.h" #include "tkm_utils.h" @@ -39,6 +40,133 @@ struct private_tkm_listener_t { }; +/** + * Build a TKM certificate chain context with given cc id. + * + * @param ike_sa IKE SA containing auth config to build certificate chain from + * @param cc_id Certificate chain ID + * @return TRUE if certificate chain was built successfully, + * FALSE otherwise + */ +static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) +{ + DBG1(DBG_IKE, "building certificate chain context %llu for IKE SA %s", + cc_id, ike_sa->get_name((ike_sa_t *)ike_sa)); + + auth_cfg_t *auth; + certificate_t *cert; + enumerator_t *rounds; + rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE); + while(rounds->enumerate(rounds, &auth)) + { + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + /* set user certificate */ + chunk_t enc_user_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded user certificate"); + rounds->destroy(rounds); + return FALSE; + } + + certificate_type user_cert; + chunk_to_sequence(&enc_user_cert, &user_cert, + sizeof(certificate_type)); + chunk_free(&enc_user_cert); + if (ike_cc_set_user_certificate(cc_id, 1, 1, user_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error setting user certificate of cert chain" + " (cc_id: %llu)", cc_id); + rounds->destroy(rounds); + return FALSE; + } + + /* process intermediate CA certificates */ + auth_rule_t rule; + enumerator_t *enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_IM_CERT) + { + chunk_t enc_im_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded intermediate CA" + " certificate"); + rounds->destroy(rounds); + enumerator->destroy(enumerator); + return FALSE; + } + + certificate_type im_cert; + chunk_to_sequence(&enc_im_cert, &im_cert, + sizeof(certificate_type)); + chunk_free(&enc_im_cert); + if (ike_cc_add_certificate(cc_id, 1, im_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error adding intermediate certificate to" + " cert chain (cc_id: %llu)", cc_id); + rounds->destroy(rounds); + enumerator->destroy(enumerator); + return FALSE; + } + } + } + enumerator->destroy(enumerator); + + /* finally add CA certificate */ + cert = auth->get(auth, AUTH_RULE_CA_CERT); + if (cert) + { + chunk_t enc_ca_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded CA certificate"); + rounds->destroy(rounds); + return FALSE; + } + + const ca_id_type ca_id = 1; + certificate_type ca_cert; + chunk_to_sequence(&enc_ca_cert, &ca_cert, + sizeof(certificate_type)); + chunk_free(&enc_ca_cert); + if (ike_cc_add_certificate(cc_id, 1, ca_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error adding CA certificate to cert chain " + "(cc_id: %llu)", cc_id); + rounds->destroy(rounds); + return FALSE; + } + + if (ike_cc_check_ca(cc_id, ca_id) != TKM_OK) + { + DBG1(DBG_IKE, "certificate chain (cc_id: %llu) not based on" + " trusted CA (ca_id: %llu)", cc_id, ca_id); + rounds->destroy(rounds); + return FALSE; + } + + rounds->destroy(rounds); + return TRUE; + } + else + { + DBG1(DBG_IKE, "no CA certificate"); + } + } + else + { + DBG1(DBG_IKE, "no subject certificate for remote peer"); + } + } + + rounds->destroy(rounds); + return FALSE; +} + METHOD(listener_t, authorize, bool, private_tkm_listener_t *this, ike_sa_t *ike_sa, bool final, bool *success) @@ -52,6 +180,21 @@ METHOD(listener_t, authorize, bool, const isa_id_type isa_id = keymat->get_isa_id(keymat); DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id); + const cc_id_type cc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_CC); + if (!cc_id) + { + DBG1(DBG_IKE, "unable to acquire CC context id"); + *success = FALSE; + return TRUE; + } + const bool cc_success = build_cert_chain(ike_sa, cc_id); + if (!cc_success) + { + DBG1(DBG_IKE, "unable to build certificate chain"); + *success = FALSE; + return TRUE; + } + const chunk_t * const auth = keymat->get_auth_payload(keymat); if (!auth->ptr) { -- cgit v1.2.3 From 49b1fdb24aa610b9ec9a8af5dbcb14442719b603 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 7 Nov 2012 17:54:24 +0100 Subject: Store peer IKE init message The IKE init message sent to us by the peer is needed for authentication in the authorization hook. Store the message as chunk in the keymat and provide a getter to make it available. --- src/charon-tkm/src/tkm/tkm_keymat.c | 19 +++++++++++++++++++ src/charon-tkm/src/tkm/tkm_keymat.h | 7 +++++++ 2 files changed, 26 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 9beb10430..2fc5d60eb 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -66,6 +66,11 @@ struct private_tkm_keymat_t { */ chunk_t auth_payload; + /** + * Peer init message chunk. + */ + chunk_t other_init_msg; + }; /** @@ -357,6 +362,11 @@ METHOD(keymat_v2_t, get_auth_octets, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) { + if (verify) + { + /* store peer init message for authentication step */ + this->other_init_msg = chunk_clone(ike_sa_init); + } DBG1(DBG_IKE, "returning auth octets"); *octets = chunk_empty; return TRUE; @@ -432,6 +442,7 @@ METHOD(keymat_t, destroy, void, DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); chunk_free(&this->auth_payload); + chunk_free(&this->other_init_msg); free(this); } @@ -453,6 +464,12 @@ METHOD(tkm_keymat_t, get_auth_payload, chunk_t*, return &this->auth_payload; } +METHOD(tkm_keymat_t, get_peer_init_msg, chunk_t*, + private_tkm_keymat_t *this) +{ + return &this->other_init_msg; +} + /** * See header. */ @@ -479,11 +496,13 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .get_isa_id = _get_isa_id, .set_auth_payload = _set_auth_payload, .get_auth_payload = _get_auth_payload, + .get_peer_init_msg = _get_peer_init_msg, }, .initiator = initiator, .isa_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ISA), .ae_ctx_id = 0, .auth_payload = chunk_empty, + .other_init_msg = chunk_empty, ); if (!this->isa_ctx_id) diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index 16f2f2a49..207f9728e 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -52,6 +52,13 @@ struct tkm_keymat_t { */ chunk_t* (*get_auth_payload)(tkm_keymat_t * const this); + /** + * Get IKE init message of peer. + * + * @return init message if set, chunk_empty otherwise + */ + chunk_t* (*get_peer_init_msg)(tkm_keymat_t * const this); + }; /** -- cgit v1.2.3 From 832488b14a43bdb31bc83053b81d72286c2739be Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 7 Nov 2012 17:55:47 +0100 Subject: Authenticate ISA using certificates The authentication of the ISA is now done using the certificate provided by the peer. --- src/charon-tkm/src/tkm/tkm_listener.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 5820990f4..cab9b4e05 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -202,9 +202,19 @@ METHOD(listener_t, authorize, bool, *success = FALSE; } + const chunk_t * const other_init_msg = keymat->get_peer_init_msg(keymat); + if (!other_init_msg->ptr) + { + DBG1(DBG_IKE, "no peer init message available"); + *success = FALSE; + } + signature_type signature; chunk_to_sequence(auth, &signature, sizeof(signature_type)); - if (ike_isa_auth_psk(isa_id, signature) != TKM_OK) + init_message_type init_msg; + chunk_to_sequence(other_init_msg, &init_msg, sizeof(init_message_type)); + + if (ike_isa_auth(isa_id, cc_id, init_msg, signature) != TKM_OK) { DBG1(DBG_IKE, "TKM based authentication failed" " for ISA context %llu", isa_id); -- cgit v1.2.3 From 9a5c51c44f975add3c939c727187beaada2036ee Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Thu, 8 Nov 2012 11:00:21 +0100 Subject: Add TKM public key implementation The key unconditionally returns TRUE for the verify operation if it is called with a supported signature algorithm. All such verification operations are performed by the TKM (e.g. trustchain or auth octets verification) anyway, so this is safe. --- src/charon-tkm/src/tkm/tkm_public_key.c | 167 ++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_public_key.h | 46 +++++++++ 2 files changed, 213 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_public_key.c create mode 100644 src/charon-tkm/src/tkm/tkm_public_key.h (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_public_key.c b/src/charon-tkm/src/tkm/tkm_public_key.c new file mode 100644 index 000000000..d56f65269 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_public_key.c @@ -0,0 +1,167 @@ +/* + * 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 . + * + * 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 + +#include "tkm_public_key.h" + +typedef struct private_tkm_public_key_t private_tkm_public_key_t; + +/** + * Private data of tkm_public_key_t object. + */ +struct private_tkm_public_key_t { + + /** + * Public interface for this signer. + */ + tkm_public_key_t public; + + /** + * Public modulus. + */ + chunk_t n; + + /** + * Public exponent. + */ + chunk_t e; + + /** + * Reference count. + */ + refcount_t ref; +}; + +METHOD(public_key_t, get_type, key_type_t, + private_tkm_public_key_t *this) +{ + return KEY_RSA; +} + +METHOD(public_key_t, verify, bool, + private_tkm_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t signature) +{ + return TRUE; +} + +METHOD(public_key_t, encrypt_, bool, + private_tkm_public_key_t *this, encryption_scheme_t scheme, + chunk_t plain, chunk_t *crypto) +{ + return FALSE; +} + +METHOD(public_key_t, get_keysize, int, + private_tkm_public_key_t *this) +{ + return 0; +} + +METHOD(public_key_t, get_encoding, bool, + private_tkm_public_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return NULL; +} + +METHOD(public_key_t, get_fingerprint, bool, + private_tkm_public_key_t *this, cred_encoding_type_t type, chunk_t *fp) +{ + if (lib->encoding->get_cache(lib->encoding, type, this, fp)) + { + return TRUE; + } + return lib->encoding->encode(lib->encoding, type, this, fp, + CRED_PART_RSA_MODULUS, this->n, + CRED_PART_RSA_PUB_EXP, this->e, + CRED_PART_END); +} + +METHOD(public_key_t, get_ref, public_key_t*, + private_tkm_public_key_t *this) +{ + ref_get(&this->ref); + return &this->public.key; +} + +METHOD(public_key_t, destroy, void, + private_tkm_public_key_t *this) +{ + if (ref_put(&this->ref)) + { + lib->encoding->clear_cache(lib->encoding, this); + chunk_free(&this->n); + chunk_free(&this->e); + free(this); + } +} + +/** + * See header. + */ +tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args) +{ + private_tkm_public_key_t *this; + chunk_t n, e; + + n = e = chunk_empty; + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_RSA_MODULUS: + n = va_arg(args, chunk_t); + continue; + case BUILD_RSA_PUB_EXP: + e = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + if (!e.ptr || !n.ptr) + { + return NULL; + } + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .verify = _verify, + .encrypt = _encrypt_, + .equals = public_key_equals, + .get_keysize = _get_keysize, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = public_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .ref = 1, + .n = chunk_clone(n), + .e = chunk_clone(e), + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_public_key.h b/src/charon-tkm/src/tkm/tkm_public_key.h new file mode 100644 index 000000000..a469f7524 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_public_key.h @@ -0,0 +1,46 @@ +/* + * 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 . + * + * 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_PUBLIC_KEY_H_ +#define TKM_PUBLIC_KEY_H_ + +#include + +typedef struct tkm_public_key_t tkm_public_key_t; + +/** + * TKM public_key_t implementation. + */ +struct tkm_public_key_t { + + /** + * Implements the public_key_t interface + */ + public_key_t key; +}; + +/** + * Load a TKM public key. + * + * Accepts BUILD_RSA_* components. + * + * @param type type of the key, must be KEY_RSA + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args); + +#endif /** TKM_PUBLIC_KEY_H_ @}*/ -- cgit v1.2.3 From ac90fcee2fde4322d829f839e1bb3d7ceac099d6 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Thu, 8 Nov 2012 11:04:48 +0100 Subject: charon-tkm: Register TKM public key on startup --- src/charon-tkm/src/charon-tkm.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index f7b59008c..59c3ffaad 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -39,6 +39,7 @@ #include "tkm_keymat.h" #include "tkm_listener.h" #include "tkm_kernel_ipsec.h" +#include "tkm_public_key.h" /** * TKM bus listener for IKE authorize events. @@ -285,6 +286,10 @@ int main(int argc, char *argv[]) PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), PLUGIN_PROVIDE(DH, MODP_3072_BIT), PLUGIN_PROVIDE(DH, MODP_4096_BIT), + PLUGIN_REGISTER(PUBKEY, tkm_public_key_load, TRUE), + PLUGIN_PROVIDE(PUBKEY, KEY_RSA), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA256), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), PLUGIN_DEPENDS(RNG, RNG_WEAK), -- cgit v1.2.3 From a2f97ff8607912a0955f48322153b8d20c551b66 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 16 Oct 2012 16:39:54 +0200 Subject: Add AUTH signature info data structure The sign_info_t type is used to transfer an ISA context id and the initial message from the keymat to the TKM private key sign operation. --- src/charon-tkm/src/tkm/tkm_types.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index 28c4d9948..96a3bb273 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -74,6 +74,7 @@ typedef struct isa_info_t isa_info_t; /** * IKE SA info data structure. + * * This type is used to transfer ISA information from the keymat of the parent * SA to the keymat of the new IKE SA. For this purpose the skd data chunk is * (ab)used. This is possible since the sk_d chunk is treated as an opaque value @@ -94,4 +95,29 @@ struct isa_info_t { }; +typedef struct sign_info_t sign_info_t; + +/** + * AUTH signature info data structure. + * + * This type is used to transfer an ISA context id and the initial message + * from the keymat to the TKM private key sign operation. For this purpose the + * auth octets chunk is (ab)used and the data is stored in this chunk. + * This is possible since the auth octets are treated as opaque value and handed + * to the private key sign function as-is without any processing. + */ +struct sign_info_t { + + /** + * ISA context id. + */ + isa_id_type isa_id; + + /** + * Init message. + */ + chunk_t init_message; + +}; + #endif /** TKM_TYPES_H_ */ -- cgit v1.2.3 From fe504b745d1a4eaf49fa60d62dc351aae1de1f93 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 16 Oct 2012 16:42:23 +0200 Subject: keymat: Store signature info in auth octets Store the ISA context id and the initial message in the auth octets chunk using the sign_info_t struct. Charon will pass on this information to the TKM private key sign operation where it is extracted. --- src/charon-tkm/src/tkm/tkm_keymat.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 2fc5d60eb..95261d8c3 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -366,9 +366,21 @@ METHOD(keymat_v2_t, get_auth_octets, bool, { /* store peer init message for authentication step */ this->other_init_msg = chunk_clone(ike_sa_init); + *octets = chunk_empty; + return TRUE; } - DBG1(DBG_IKE, "returning auth octets"); - *octets = chunk_empty; + + sign_info_t *sign; + INIT(sign, + .isa_id = this->isa_ctx_id, + .init_message = chunk_clone(ike_sa_init), + ); + + /* + * store signature info in AUTH octets, which is passed to the private key + * sign() operation + */ + *octets = chunk_create((u_char *)sign, sizeof(sign_info_t)); return TRUE; } -- cgit v1.2.3 From 08d199fa3d02e1954e1c09fcabf98bb3d1ede675 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 16 Oct 2012 16:27:46 +0200 Subject: Add TKM private key implementation The key currently imitates the private key of alice@strongswan.org by returning it's fingerprint in the get_fingerprint function. This associates the private key with alice's X.509 cert and charon will use it to create a signature over the local AUTH octets of the test connection. The private key serves as a proxy to the TKM ike_isa_sign operation and extracts the required information from the auth octets chunk passed on by the keymat. --- src/charon-tkm/src/tkm/tkm_private_key.c | 166 +++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_private_key.h | 40 ++++++++ 2 files changed, 206 insertions(+) create mode 100644 src/charon-tkm/src/tkm/tkm_private_key.c create mode 100644 src/charon-tkm/src/tkm/tkm_private_key.h (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_private_key.c b/src/charon-tkm/src/tkm/tkm_private_key.c new file mode 100644 index 000000000..d728f8d7e --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_private_key.c @@ -0,0 +1,166 @@ +/* + * 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 . + * + * 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 +#include +#include + +#include "tkm_utils.h" +#include "tkm_types.h" +#include "tkm_private_key.h" + +typedef struct private_tkm_private_key_t private_tkm_private_key_t; + +/** + * Private data of a tkm_private_key_t object. + */ +struct private_tkm_private_key_t { + + /** + * Public interface for this signer. + */ + tkm_private_key_t public; + + /** + * Key fingerprint. + */ + chunk_t fingerprint; + + /** + * Reference count. + */ + refcount_t ref; + +}; + +METHOD(private_key_t, get_type, key_type_t, + private_tkm_private_key_t *this) +{ + return KEY_RSA; +} + +METHOD(private_key_t, sign, bool, + private_tkm_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) +{ + signature_type sig; + init_message_type msg; + + if (data.ptr == NULL) + { + DBG1(DBG_LIB, "unable to get signature information"); + return FALSE; + } + sign_info_t sign = *(sign_info_t *)(data.ptr); + + chunk_to_sequence(&sign.init_message, &msg, sizeof(init_message_type)); + const isa_id_type isa_id = sign.isa_id; + chunk_free(&sign.init_message); + + if (ike_isa_sign(isa_id, 1, msg, &sig) != TKM_OK) + { + DBG1(DBG_LIB, "signature operation failed"); + return FALSE; + } + + sequence_to_chunk(sig.data, sig.size, signature); + return TRUE; +} + +METHOD(private_key_t, decrypt, bool, + private_tkm_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) +{ + return FALSE; +} + +METHOD(private_key_t, get_keysize, int, + private_tkm_private_key_t *this) +{ + return 0; +} + +METHOD(private_key_t, get_public_key, public_key_t*, + private_tkm_private_key_t *this) +{ + return NULL; +} + +METHOD(private_key_t, get_encoding, bool, + private_tkm_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return FALSE; +} + +METHOD(private_key_t, get_fingerprint, bool, + private_tkm_private_key_t *this, cred_encoding_type_t type, chunk_t *fp) +{ + *fp = this->fingerprint; + return TRUE; +} + +METHOD(private_key_t, get_ref, private_key_t*, + private_tkm_private_key_t *this) +{ + ref_get(&this->ref); + return &this->public.key; +} + +METHOD(private_key_t, destroy, void, + private_tkm_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + chunk_free(&this->fingerprint); + free(this); + } +} + +/** + * See header. + */ +tkm_private_key_t *tkm_private_key_init(void) +{ + private_tkm_private_key_t *this; + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .sign = _sign, + .decrypt = _decrypt, + .get_keysize = _get_keysize, + .get_public_key = _get_public_key, + .equals = private_key_equals, + .belongs_to = private_key_belongs_to, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = private_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .ref = 1, + ); + + /* fingerprint of alice@strongswan.org keypair */ + const char fake_fp[] = "05da04208c02f428470acf6c772d066613da863c"; + this->fingerprint = chunk_create((u_char *)fake_fp, strlen(fake_fp)); + this->fingerprint = chunk_from_hex(this->fingerprint, NULL); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_private_key.h b/src/charon-tkm/src/tkm/tkm_private_key.h new file mode 100644 index 000000000..aa472a1a8 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_private_key.h @@ -0,0 +1,40 @@ +/* + * 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 . + * + * 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_PRIVATE_KEY_H_ +#define TKM_PRIVATE_KEY_H_ + +#include + +typedef struct tkm_private_key_t tkm_private_key_t; + +/** + * TKM private_key_t implementation. + */ +struct tkm_private_key_t { + + /** + * Implements private_key_t interface + */ + private_key_t key; +}; + +/** + * Initialize TKM private key. + */ +tkm_private_key_t *tkm_private_key_init(void); + +#endif /** TKM_PRIVATE_KEY_H_ */ -- cgit v1.2.3 From c457128ab6f532daffa8268614da6cbb51c0e482 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 16 Oct 2012 17:12:51 +0200 Subject: charon-tkm: Register TKM private key on startup --- src/charon-tkm/src/charon-tkm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 59c3ffaad..eac9a27e2 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "tkm.h" #include "tkm_nonceg.h" @@ -40,6 +41,7 @@ #include "tkm_listener.h" #include "tkm_kernel_ipsec.h" #include "tkm_public_key.h" +#include "tkm_private_key.h" /** * TKM bus listener for IKE authorize events. @@ -238,6 +240,10 @@ int main(int argc, char *argv[]) dmn_name = "charon-tkm"; } + /* credential set and TKM private key */ + mem_cred_t *creds; + tkm_private_key_t *key; + struct sigaction action; int status = SS_RC_INITIALIZATION_FAILED; @@ -341,6 +347,12 @@ int main(int argc, char *argv[]) listener = tkm_listener_create(); charon->bus->add_listener(charon->bus, &listener->listener); + /* register TKM private key */ + creds = mem_cred_create(); + key = tkm_private_key_init(); + creds->add_key(creds, (private_key_t *)key); + lib->credmgr->add_set(lib->credmgr, (credential_set_t*)creds); + /* add handler for SEGV and ILL, * INT and TERM are handled by sigwait() in run() */ action.sa_handler = segv_handler; @@ -366,6 +378,7 @@ int main(int argc, char *argv[]) status = 0; charon->bus->remove_listener(charon->bus, &listener->listener); listener->destroy(listener); + creds->destroy(creds); deinit: libcharon_deinit(); -- cgit v1.2.3 From 0f5e57fe26c02f58f16945bed96453429ff1ea57 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Thu, 8 Nov 2012 12:22:10 +0100 Subject: Drop support for pre-shared key authentication --- src/charon-tkm/src/tkm/tkm_keymat.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 95261d8c3..fe4caf9ec 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -408,29 +408,7 @@ METHOD(keymat_v2_t, get_psk_sig, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig) { - DBG1(DBG_IKE, "returning %s PSK signature", verify ? "remote" : "local"); - - signature_type signature; - init_message_type msg; - chunk_to_sequence(&ike_sa_init, &msg, sizeof(init_message_type)); - - chunk_t idx_chunk, chunk = chunk_alloca(4); - chunk.ptr[0] = id->get_type(id); - memcpy(chunk.ptr + 1, reserved, 3); - idx_chunk = chunk_cata("cc", chunk, id->get_encoding(id)); - idx_type idx; - chunk_to_sequence(&idx_chunk, &idx, sizeof(idx_type)); - - if (ike_isa_sign_psk(this->isa_ctx_id, msg, idx, verify == TRUE, &signature) - != TKM_OK) - { - DBG1(DBG_IKE, "get %s PSK signature failed", verify ? - "remote" : "local"); - return FALSE; - } - - sequence_to_chunk(&signature.data[0], signature.size, sig); - return TRUE; + return FALSE; } METHOD(keymat_t, destroy, void, -- cgit v1.2.3 From 3360bad9106938751cf06fd8a64bfe1e1c3d6940 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 8 Nov 2012 15:32:54 +0100 Subject: Remove result out parameter from EES Init Error processing is done by the registered exception handler. --- src/charon-tkm/src/ees/esa_event_service.adb | 10 +--------- src/charon-tkm/src/ees/esa_event_service.ads | 7 +------ src/charon-tkm/src/tkm/tkm.c | 8 ++------ 3 files changed, 4 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/ees/esa_event_service.adb b/src/charon-tkm/src/ees/esa_event_service.adb index 7b35090af..5b5d7003b 100644 --- a/src/charon-tkm/src/ees/esa_event_service.adb +++ b/src/charon-tkm/src/ees/esa_event_service.adb @@ -45,21 +45,13 @@ is ------------------------------------------------------------------------- - procedure Init - (Result : out Tkmrpc.Results.Result_Type; - Address : Interfaces.C.Strings.chars_ptr) + procedure Init (Address : Interfaces.C.Strings.chars_ptr) is Path : constant String := Interfaces.C.Strings.Value (Address); begin Sock.Init; Sock.Bind (Path => Anet.Sockets.Unix.Path_Type (Path)); Receiver.Listen (Callback => Dispatch'Access); - - Result := Tkmrpc.Results.Ok; - - exception - when others => - Result := Tkmrpc.Results.Invalid_Operation; end Init; end Esa_Event_Service; diff --git a/src/charon-tkm/src/ees/esa_event_service.ads b/src/charon-tkm/src/ees/esa_event_service.ads index 5ead0ca0c..f3630b7ac 100644 --- a/src/charon-tkm/src/ees/esa_event_service.ads +++ b/src/charon-tkm/src/ees/esa_event_service.ads @@ -16,16 +16,11 @@ with Interfaces.C.Strings; -with Tkmrpc.Results; - package Esa_Event_Service is - procedure Init - (Result : out Tkmrpc.Results.Result_Type; - Address : Interfaces.C.Strings.chars_ptr); + procedure Init (Address : Interfaces.C.Strings.chars_ptr); pragma Export (C, Init, "ees_server_init"); - pragma Export_Valued_Procedure (Init); -- Initialize Esa Event Service (EES) with given address. procedure Finalize; diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index ce4cedcbc..47e1eb963 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -69,12 +69,8 @@ bool tkm_init() tkmlib_final(); return FALSE; } - /* init esa event service */ - if (ees_server_init(EES_SOCKET) != TKM_OK) - { - tkmlib_final(); - return FALSE; - } + + ees_server_init(EES_SOCKET); if (ike_tkm_reset() != TKM_OK) { -- cgit v1.2.3 From d2371b728c645e93823a82b2ffc1b587e1b2b32f Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 12 Nov 2012 12:08:32 +0100 Subject: Check that chunk fits into sequence when converting --- src/charon-tkm/src/tkm/tkm_utils.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_utils.c b/src/charon-tkm/src/tkm/tkm_utils.c index 28fcdd1d1..e0c3e5752 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.c +++ b/src/charon-tkm/src/tkm/tkm_utils.c @@ -14,6 +14,8 @@ * for more details. */ +#include + #include "tkm_utils.h" /* Generic variable-length sequence */ @@ -33,8 +35,18 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, void chunk_to_sequence(const chunk_t * const chunk, void *sequence, const uint32_t typelen) { + const uint32_t seqlenmax = typelen - sizeof(uint32_t); memset(sequence, 0, typelen); sequence_type *seq = sequence; - seq->size = chunk->len; + if (chunk->len > seqlenmax) + { + DBG1(DBG_LIB, "chunk too large to fit into sequence %d > %d, limiting" + " to %d bytes", chunk->len, seqlenmax, seqlenmax); + seq->size = seqlenmax; + } + else + { + seq->size = chunk->len; + } memcpy(seq->data, chunk->ptr, seq->size); } -- cgit v1.2.3 From 1c1400f0079f7ded06ad66156d6d0398358fe1c2 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 12 Nov 2012 19:05:28 +0100 Subject: Call Esa_Select after creation of child SA This tells the TKM which child SA is the currently active SA. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 4e813a035..623942b62 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -169,6 +169,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t, } tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id); } + if (ike_esa_select(esa_id) != TKM_OK) + { + DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id); + if (ike_esa_reset(esa_id) != TKM_OK) + { + DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id); + } + goto failure; + } + DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, " "esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc), ntohl(spi_rem), initiator ? "initiator" : "responder"); -- cgit v1.2.3 From 722d68803ee65c41585cbdd075817d6b6a280ae6 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 17 Dec 2012 17:21:47 +0100 Subject: Set sp_id to reqid when creating ESA The reqid corresponds to the sp_id (security policy id) on the TKM side. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 623942b62..d60b8e5ae 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -134,7 +134,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, */ if (nonce_loc_id == 0 && esa.dh_id == 0) { - if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(spi_loc), + if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, ntohl(spi_loc), ntohl(spi_rem)) != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id); @@ -146,7 +146,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); - if (ike_esa_create_no_pfs(esa_id, esa.isa_id, 1, 1, nonce_loc_id, + if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id, nc_rem, initiator, ntohl(spi_loc), ntohl(spi_rem)) != TKM_OK) { @@ -160,7 +160,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); - if (ike_esa_create(esa_id, esa.isa_id, 1, 1, esa.dh_id, nonce_loc_id, + if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id, nc_rem, initiator, ntohl(spi_loc), ntohl(spi_rem)) != TKM_OK) { -- cgit v1.2.3 From 9099d2ba0b9dfcde773ec9ae577d95a6bcfb48d3 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 17 Dec 2012 18:27:03 +0100 Subject: Set ri_id to reqid when setting user certificate Pass the reqid (of the first child config of an IKE SA) as remote identity id when calling cc_set_user_certificate. May lead to the usage of the wrong id in case an IKE SA has multiple child configurations/reqids. This must be replaced with a proper lookup once the configuration backend is implemented and provides remote identity ids to charon-tkm. --- src/charon-tkm/src/tkm/tkm_listener.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index cab9b4e05..1ec8e122a 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -40,6 +40,32 @@ struct private_tkm_listener_t { }; +/** + * Return id of remote identity. + * + * TODO: Replace this with the lookup for the remote identitiy id. + * + * Currently the reqid of the first child SA in peer config of IKE SA is + * returned. Might choose wrong reqid if IKE SA has multiple child configs + * with different reqids. + * + * @param peer_cfg Remote peer config + * @return remote identity id if found, 0 otherwise + */ +static ri_id_type get_remote_identity_id(peer_cfg_t *peer) +{ + ri_id_type remote_id = 0; + child_cfg_t *child; + enumerator_t* children = peer->create_child_cfg_enumerator(peer); + + /* pick the reqid of the first child, no need to enumerate all children. */ + children->enumerate(children, &child); + remote_id = child->get_reqid(child); + children->destroy(children); + + return remote_id; +} + /** * Build a TKM certificate chain context with given cc id. * @@ -57,7 +83,7 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) certificate_t *cert; enumerator_t *rounds; rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE); - while(rounds->enumerate(rounds, &auth)) + while (rounds->enumerate(rounds, &auth)) { cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); if (cert) @@ -71,11 +97,12 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) return FALSE; } + ri_id_type ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa)); certificate_type user_cert; chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type)); chunk_free(&enc_user_cert); - if (ike_cc_set_user_certificate(cc_id, 1, 1, user_cert) != TKM_OK) + if (ike_cc_set_user_certificate(cc_id, ri_id, 1, user_cert) != TKM_OK) { DBG1(DBG_IKE, "error setting user certificate of cert chain" " (cc_id: %llu)", cc_id); -- cgit v1.2.3 From ec169572a0092cbcd43c4f712f9b99d52f0326da Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 18 Dec 2012 15:06:07 +0100 Subject: Initialize libstrongswan in test_runner main() --- src/charon-tkm/tests/keymat_tests.c | 54 ------------------------------------- src/charon-tkm/tests/test_runner.c | 41 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index e4c59fa64..2a7525d4e 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -19,40 +19,16 @@ #include #include #include -#include #include #include "tkm.h" #include "tkm_nonceg.h" #include "tkm_diffie_hellman.h" #include "tkm_keymat.h" -#include "tkm_kernel_ipsec.h" #include "tkm_types.h" START_TEST(test_derive_ike_keys) { - fail_if(!library_init(NULL), "Unable to init library"); - fail_if(!libhydra_init("tkm-tests"), "Unable to init libhydra"); - fail_if(!libcharon_init("tkm-tests"), "Unable to init libcharon"); - - /* Register TKM specific plugins */ - static plugin_feature_t features[] = { - PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), - PLUGIN_PROVIDE(NONCE_GEN), - PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), - PLUGIN_PROVIDE(DH, MODP_3072_BIT), - PLUGIN_PROVIDE(DH, MODP_4096_BIT), - PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), - PLUGIN_DEPENDS(RNG, RNG_WEAK), - PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-net"), - }; - lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, - countof(features), TRUE); - - fail_if(!charon->initialize(charon, PLUGINS), "Unable to init charon"); - proposal_t *proposal = proposal_create_from_string(PROTO_IKE, "aes256-sha512-modp4096"); fail_if(!proposal, "Unable to create proposal"); @@ -97,37 +73,11 @@ START_TEST(test_derive_ike_keys) ike_sa_id->destroy(ike_sa_id); keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); chunk_free(&pubvalue); - - libcharon_deinit(); - libhydra_deinit(); - library_deinit(); } END_TEST START_TEST(test_derive_child_keys) { - fail_if(!library_init(NULL), "Unable to init library"); - fail_if(!libhydra_init("tkm-tests"), "Unable to init libhydra"); - fail_if(!libcharon_init("tkm-tests"), "Unable to init libcharon"); - - /* Register TKM specific plugins */ - static plugin_feature_t features[] = { - PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), - PLUGIN_PROVIDE(NONCE_GEN), - PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), - PLUGIN_PROVIDE(DH, MODP_3072_BIT), - PLUGIN_PROVIDE(DH, MODP_4096_BIT), - PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), - PLUGIN_DEPENDS(RNG, RNG_WEAK), - PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-net"), - }; - lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, - countof(features), TRUE); - - fail_if(!charon->initialize(charon, PLUGINS), "Unable to init charon"); - tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT); fail_if(!dh, "Unable to create DH object"); proposal_t *proposal = proposal_create_from_string(PROTO_ESP, @@ -186,10 +136,6 @@ START_TEST(test_derive_child_keys) keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); chunk_free(&encr_i); chunk_free(&encr_r); - - libcharon_deinit(); - libhydra_deinit(); - library_deinit(); } END_TEST diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index b716dc633..b22f1ff20 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -14,11 +14,49 @@ * for more details. */ +#include +#include +#include +#include + #include "tkm.h" +#include "tkm_nonceg.h" +#include "tkm_diffie_hellman.h" +#include "tkm_kernel_ipsec.h" #include "test_runner.h" int main(void) { + library_init(NULL); + libhydra_init("test_runner"); + libcharon_init("test_runner"); + + lib->settings->set_int(lib->settings, "test_runner.filelog.stdout.default", + 1); + charon->load_loggers(charon, NULL, FALSE); + + /* Register TKM specific plugins */ + static plugin_feature_t features[] = { + PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), + PLUGIN_PROVIDE(NONCE_GEN), + PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), + PLUGIN_PROVIDE(DH, MODP_3072_BIT), + PLUGIN_PROVIDE(DH, MODP_4096_BIT), + PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), + PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + }; + lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, + countof(features), TRUE); + + if (!charon->initialize(charon, PLUGINS)) + { + fprintf(stderr, "Unable to init charon"); + return EXIT_FAILURE; + } + if (!tkm_init()) { fprintf(stderr, "Could not connect to TKM, aborting tests\n"); @@ -41,6 +79,9 @@ int main(void) number_failed = srunner_ntests_failed(sr); tkm_deinit(); + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); srunner_free(sr); return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -- cgit v1.2.3 From f47ea969f88ad0d8a827cf99bf73472a7f29f07c Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 18 Dec 2012 15:35:40 +0100 Subject: Implement TKM-specific credential set The TKM credential set extends the in-memory credential set. It provides a private key enumerator which is used to instantiate private key proxy objects on-demand. This allows the usage of private keys with arbitrary identifiers. --- src/charon-tkm/src/charon-tkm.c | 15 ++-- src/charon-tkm/src/tkm/tkm_cred.c | 146 +++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_cred.h | 46 ++++++++++ src/charon-tkm/src/tkm/tkm_private_key.c | 16 ++-- src/charon-tkm/src/tkm/tkm_private_key.h | 4 +- 5 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 src/charon-tkm/src/tkm/tkm_cred.c create mode 100644 src/charon-tkm/src/tkm/tkm_cred.h (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index eac9a27e2..7afde6e18 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "tkm.h" #include "tkm_nonceg.h" @@ -41,7 +41,7 @@ #include "tkm_listener.h" #include "tkm_kernel_ipsec.h" #include "tkm_public_key.h" -#include "tkm_private_key.h" +#include "tkm_cred.h" /** * TKM bus listener for IKE authorize events. @@ -240,9 +240,8 @@ int main(int argc, char *argv[]) dmn_name = "charon-tkm"; } - /* credential set and TKM private key */ - mem_cred_t *creds; - tkm_private_key_t *key; + /* TKM credential set */ + tkm_cred_t *creds; struct sigaction action; int status = SS_RC_INITIALIZATION_FAILED; @@ -347,10 +346,8 @@ int main(int argc, char *argv[]) listener = tkm_listener_create(); charon->bus->add_listener(charon->bus, &listener->listener); - /* register TKM private key */ - creds = mem_cred_create(); - key = tkm_private_key_init(); - creds->add_key(creds, (private_key_t *)key); + /* register TKM credential set */ + creds = tkm_cred_create(); lib->credmgr->add_set(lib->credmgr, (credential_set_t*)creds); /* add handler for SEGV and ILL, diff --git a/src/charon-tkm/src/tkm/tkm_cred.c b/src/charon-tkm/src/tkm/tkm_cred.c new file mode 100644 index 000000000..cf591d4e3 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_cred.c @@ -0,0 +1,146 @@ +/* + * 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 . + * + * 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 +#include +#include +#include + +#include "tkm_private_key.h" +#include "tkm_cred.h" + +typedef struct private_tkm_cred_t private_tkm_cred_t; + +/** + * Private data of a tkm_cred_t object. + */ +struct private_tkm_cred_t { + + /** + * Public tkm_cred_t interface. + */ + tkm_cred_t public; + + /** + * In-memory credential set. + */ + mem_cred_t *creds; + + /** + * Key-id hashtable. + */ + hashtable_t *known_keys; + + /** + * rwlock for hashtable. + */ + rwlock_t *lock; + +}; + +METHOD(credential_set_t, create_private_enumerator, enumerator_t*, + private_tkm_cred_t *this, key_type_t type, identification_t *id) +{ + if (!id) + { + return this->known_keys->create_enumerator(this->known_keys); + } + + identification_t *entry; + this->lock->write_lock(this->lock); + entry = this->known_keys->get(this->known_keys, id); + + if (!entry) + { + identification_t *clone = id->clone(id); + DBG1(DBG_CFG, "adding private key proxy for id '%Y'", clone); + tkm_private_key_t *key = tkm_private_key_init(id); + if (!key) + { + DBG1(DBG_CFG, "unable to create private key for id '%Y'", clone); + this->lock->unlock(this->lock); + return NULL; + } + this->creds->add_key(this->creds, (private_key_t *)key); + entry = this->known_keys->put(this->known_keys, clone, clone); + } + this->lock->unlock(this->lock); + + return this->creds->set.create_private_enumerator(&this->creds->set, + type, id); +} + +METHOD(tkm_cred_t, destroy, void, + private_tkm_cred_t *this) +{ + enumerator_t *enumerator; + identification_t *entry; + + enumerator = this->known_keys->create_enumerator(this->known_keys); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + entry->destroy(entry); + } + enumerator->destroy(enumerator); + this->known_keys->destroy(this->known_keys); + + this->creds->destroy(this->creds); + this->lock->destroy(this->lock); + free(this); +} + +/** + * Hashtable hash function. + */ +static u_int hash(identification_t *id) +{ + return chunk_hash(id->get_encoding(id)); +} + +/** + * Hashtable equals function. + */ +static bool equals(identification_t *a, identification_t *b) +{ + return a->equals(a, b); +} + +/** + * See header + */ +tkm_cred_t *tkm_cred_create() +{ + private_tkm_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_shared_enumerator = (void*)return_null, + .create_private_enumerator = _create_private_enumerator, + .create_cert_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .creds = mem_cred_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .known_keys = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 4), + ); + + return &this->public; +} diff --git a/src/charon-tkm/src/tkm/tkm_cred.h b/src/charon-tkm/src/tkm/tkm_cred.h new file mode 100644 index 000000000..362e228c8 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_cred.h @@ -0,0 +1,46 @@ +/* + * 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 . + * + * 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_CRED_H_ +#define TKM_CRED_H_ + +typedef struct tkm_cred_t tkm_cred_t; + +#include + +/** + * TKM in-memory credential set. + */ +struct tkm_cred_t { + + /** + * Implements credential_set_t. + */ + credential_set_t set; + + /** + * Destroy a tkm_cred_t. + */ + void (*destroy)(tkm_cred_t *this); + +}; + +/** + * Create a tkm_cred instance. + */ +tkm_cred_t *tkm_cred_create(); + +#endif /** TKM_CRED_H_ */ diff --git a/src/charon-tkm/src/tkm/tkm_private_key.c b/src/charon-tkm/src/tkm/tkm_private_key.c index d728f8d7e..616941454 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.c +++ b/src/charon-tkm/src/tkm/tkm_private_key.c @@ -35,9 +35,9 @@ struct private_tkm_private_key_t { tkm_private_key_t public; /** - * Key fingerprint. + * Key ID. */ - chunk_t fingerprint; + identification_t *id; /** * Reference count. @@ -109,7 +109,7 @@ METHOD(private_key_t, get_encoding, bool, METHOD(private_key_t, get_fingerprint, bool, private_tkm_private_key_t *this, cred_encoding_type_t type, chunk_t *fp) { - *fp = this->fingerprint; + *fp = this->id->get_encoding(this->id); return TRUE; } @@ -125,7 +125,7 @@ METHOD(private_key_t, destroy, void, { if (ref_put(&this->ref)) { - chunk_free(&this->fingerprint); + this->id->destroy(this->id); free(this); } } @@ -133,7 +133,7 @@ METHOD(private_key_t, destroy, void, /** * See header. */ -tkm_private_key_t *tkm_private_key_init(void) +tkm_private_key_t *tkm_private_key_init(identification_t * const id) { private_tkm_private_key_t *this; @@ -155,12 +155,8 @@ tkm_private_key_t *tkm_private_key_init(void) }, }, .ref = 1, + .id = id->clone(id), ); - /* fingerprint of alice@strongswan.org keypair */ - const char fake_fp[] = "05da04208c02f428470acf6c772d066613da863c"; - this->fingerprint = chunk_create((u_char *)fake_fp, strlen(fake_fp)); - this->fingerprint = chunk_from_hex(this->fingerprint, NULL); - return &this->public; } diff --git a/src/charon-tkm/src/tkm/tkm_private_key.h b/src/charon-tkm/src/tkm/tkm_private_key.h index aa472a1a8..343752f28 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.h +++ b/src/charon-tkm/src/tkm/tkm_private_key.h @@ -33,8 +33,8 @@ struct tkm_private_key_t { }; /** - * Initialize TKM private key. + * Initialize TKM private key with given key ID. */ -tkm_private_key_t *tkm_private_key_init(void); +tkm_private_key_t *tkm_private_key_init(identification_t * const id); #endif /** TKM_PRIVATE_KEY_H_ */ -- cgit v1.2.3 From 140a6b7b34f5f0f7694da74195fd90454298c9a6 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Tue, 18 Dec 2012 17:15:58 +0100 Subject: Make IKE and EES sockets configurable The IKE and EES sockets are now read from strongswan.conf. They can be specified like this: charon-tkm { ike_socket = /tmp/tkm.rpc.ike ees_socket = /tmp/tkm.rpc.ees } The socket names given above are used by default if none are configured. --- src/charon-tkm/src/tkm/tkm.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 47e1eb963..9cf54b087 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -14,6 +14,8 @@ * for more details. */ +#include + #include #include @@ -61,16 +63,25 @@ bool tkm_init() /* initialize TKM client library */ tkmlib_init(); - ehandler_init(); - if (ike_init(IKE_SOCKET) != TKM_OK) + const char * const ikesock = lib->settings->get_str(lib->settings, + "%s.ike_socket", + IKE_SOCKET, + charon->name); + if (ike_init(ikesock) != TKM_OK) { tkmlib_final(); return FALSE; } - - ees_server_init(EES_SOCKET); + DBG1(DBG_DMN, "connected to TKM via socket '%s'", ikesock); + + const char * const eessock = lib->settings->get_str(lib->settings, + "%s.ees_socket", + EES_SOCKET, + charon->name); + ees_server_init(eessock); + DBG1(DBG_DMN, "serving EES requests on socket '%s'", eessock); if (ike_tkm_reset() != TKM_OK) { -- cgit v1.2.3 From 89b1d5f32c00283e471a51d3c26baf0919dd890c Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 19 Dec 2012 15:58:17 +0100 Subject: Call isa_skip_create_first when keeping IKE SA An ALERT_KEEP_ON_CHILD_SA_FAILURE alert is issued when child SA establishment fails but the corresponding IKE SA is not destroyed. To allow later creation of child SAs the ISA context must be signaled that the implicity first child SA creation was skipped. --- src/charon-tkm/src/tkm/tkm_listener.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 1ec8e122a..47cfef5ac 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -194,6 +194,25 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) return FALSE; } +METHOD(listener_t, alert, bool, + private_tkm_listener_t *this, ike_sa_t *ike_sa, + alert_t alert, va_list args) +{ + if (alert == ALERT_KEEP_ON_CHILD_SA_FAILURE) + { + tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + const isa_id_type isa_id = keymat->get_isa_id(keymat); + DBG1(DBG_IKE, "TKM alert listener called for ISA context %llu", isa_id); + if (ike_isa_skip_create_first(isa_id) != TKM_OK) + { + DBG1(DBG_IKE, "Skip of first child SA creation failed for ISA " + "context %llu", isa_id); + } + } + + return TRUE; +} + METHOD(listener_t, authorize, bool, private_tkm_listener_t *this, ike_sa_t *ike_sa, bool final, bool *success) @@ -305,6 +324,7 @@ tkm_listener_t *tkm_listener_create() .listener = { .authorize = _authorize, .message = _message, + .alert = _alert, }, .destroy = _destroy, }, -- cgit v1.2.3 From 41eaaef79bda9ecf8668444432100d414331c229 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Thu, 17 Jan 2013 10:01:31 +0100 Subject: Make sure IP_XFRM_POLICY is defined --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index d60b8e5ae..b0432998c 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -29,6 +29,11 @@ #include "tkm_kernel_sad.h" #include "tkm_kernel_ipsec.h" +/** From linux/in.h */ +#ifndef IP_XFRM_POLICY +#define IP_XFRM_POLICY 17 +#endif + typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t; /** -- cgit v1.2.3 From 32b2ea9edb0609eee138f803439ba2b2d5ba9228 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 23 Jan 2013 13:43:07 +0100 Subject: Move stroke plugin to the end of PLUGINS list This fixes the problem of stroke being unable to load the ca certificates on startup. --- src/charon-tkm/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 10e161dcf..62731afb1 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -32,9 +32,9 @@ PLUGINS = \ random \ sha1 \ sha2 \ - stroke \ socket-default \ - x509 + x509 \ + stroke all: build_charon -- cgit v1.2.3 From ae6f4ee39fe8a53fef977be12bb66e95c4e6134a Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 23 Jan 2013 13:51:12 +0100 Subject: Don't manually register kernel_netlink_net Load complete kernel_netlink plugin instead. Registering the TKM specific plugins first still ensures that the correct ipsec plugin is used. Lazy initialize the RNG_WEAK plugin to avoid the unsatisfiable soft dependency on startup. --- src/charon-tkm/Makefile.am | 1 + src/charon-tkm/src/charon-tkm.c | 5 ----- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 17 ++++++++++------- src/charon-tkm/tests/test_runner.c | 4 ---- 4 files changed, 11 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 62731afb1..0f4f51853 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -26,6 +26,7 @@ PLUGINS = \ aes \ constraints \ hmac \ + kernel-netlink \ pem \ pkcs1 \ pkcs8 \ diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 7afde6e18..92217b87f 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -297,10 +296,6 @@ int main(int argc, char *argv[]) PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA256), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), - PLUGIN_DEPENDS(RNG, RNG_WEAK), - PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-net"), - }; lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE); diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index b0432998c..734bec73c 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -62,6 +62,16 @@ METHOD(kernel_ipsec_t, get_spi, status_t, private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) { + if (!this->rng) + { + this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!this->rng) + { + DBG1(DBG_KNL, "unable to create RNG"); + return FAILED; + } + } + DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid); const bool result = this->rng->get_bytes(this->rng, sizeof(u_int32_t), (u_int8_t *)spi); @@ -365,16 +375,9 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create() .destroy = _destroy, }, }, - .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), .sad = tkm_kernel_sad_create(), ); - if (!this->rng) - { - DBG1(DBG_KNL, "unable to create RNG"); - destroy(this); - return NULL; - } if (!this->sad) { DBG1(DBG_KNL, "unable to create SAD"); diff --git a/src/charon-tkm/tests/test_runner.c b/src/charon-tkm/tests/test_runner.c index b22f1ff20..5ae032935 100644 --- a/src/charon-tkm/tests/test_runner.c +++ b/src/charon-tkm/tests/test_runner.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "tkm.h" #include "tkm_nonceg.h" @@ -44,9 +43,6 @@ int main(void) PLUGIN_PROVIDE(DH, MODP_4096_BIT), PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), - PLUGIN_DEPENDS(RNG, RNG_WEAK), - PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create), - PLUGIN_PROVIDE(CUSTOM, "kernel-net"), }; lib->plugins->add_static_features(lib->plugins, "tkm-tests", features, countof(features), TRUE); -- cgit v1.2.3 From 1b22565ba5364ef4b6b6483c49ddd1c0632b8c08 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Tue, 29 Jan 2013 10:28:38 +0100 Subject: Switch to openssl plugin --- src/charon-tkm/Makefile.am | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 0f4f51853..515a40571 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -23,18 +23,11 @@ BUILD_OPTS = \ # plugins to enable PLUGINS = \ - aes \ - constraints \ - hmac \ kernel-netlink \ pem \ pkcs1 \ - pkcs8 \ - random \ - sha1 \ - sha2 \ socket-default \ - x509 \ + openssl \ stroke all: build_charon -- cgit v1.2.3 From 38c1fd3cb147d78d5e83b0052c5283ee62f13ba8 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Fri, 18 Jan 2013 14:40:02 +0100 Subject: Provide TKM credential encoder The TKM credential encoder creates fingerprints of type KEYID_PUBKEY_INFO_SHA1 and KEYID_PUBKEY_SHA1 using CRED_PART_RSA_PUB_ASN1_DER. This makes the pkcs1 plugin unnecessary. --- src/charon-tkm/Makefile.am | 1 - src/charon-tkm/src/charon-tkm.c | 5 ++ src/charon-tkm/src/tkm/tkm_encoder.c | 106 ++++++++++++++++++++++++++++++++ src/charon-tkm/src/tkm/tkm_encoder.h | 28 +++++++++ src/charon-tkm/src/tkm/tkm_public_key.c | 36 ++++------- 5 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 src/charon-tkm/src/tkm/tkm_encoder.c create mode 100644 src/charon-tkm/src/tkm/tkm_encoder.h (limited to 'src') diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am index 515a40571..457e5e44e 100644 --- a/src/charon-tkm/Makefile.am +++ b/src/charon-tkm/Makefile.am @@ -25,7 +25,6 @@ BUILD_OPTS = \ PLUGINS = \ kernel-netlink \ pem \ - pkcs1 \ socket-default \ openssl \ stroke diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 92217b87f..988541e36 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -41,6 +41,7 @@ #include "tkm_kernel_ipsec.h" #include "tkm_public_key.h" #include "tkm_cred.h" +#include "tkm_encoder.h" /** * TKM bus listener for IKE authorize events. @@ -345,6 +346,9 @@ int main(int argc, char *argv[]) creds = tkm_cred_create(); lib->credmgr->add_set(lib->credmgr, (credential_set_t*)creds); + /* register TKM credential encoder */ + lib->encoding->add_encoder(lib->encoding, tkm_encoder_encode); + /* add handler for SEGV and ILL, * INT and TERM are handled by sigwait() in run() */ action.sa_handler = segv_handler; @@ -371,6 +375,7 @@ int main(int argc, char *argv[]) charon->bus->remove_listener(charon->bus, &listener->listener); listener->destroy(listener); creds->destroy(creds); + lib->encoding->remove_encoder(lib->encoding, tkm_encoder_encode); deinit: libcharon_deinit(); diff --git a/src/charon-tkm/src/tkm/tkm_encoder.c b/src/charon-tkm/src/tkm/tkm_encoder.c new file mode 100644 index 000000000..d5367ea78 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_encoder.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2013 Reto Buerki + * Copyright (C) 2013 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 . + * + * 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 +#include +#include + +#include "tkm_encoder.h" + +/** + * Build the SHA1 hash of pubkey(info) ASN.1 data. + */ +static bool hash_pubkey(chunk_t pubkey, chunk_t *hash) +{ + hasher_t *hasher; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher || !hasher->allocate_hash(hasher, pubkey, hash)) + { + DBG1(DBG_LIB, "SHA1 hash algorithm not supported, " + "fingerprinting failed"); + DESTROY_IF(hasher); + chunk_free(&pubkey); + return FALSE; + } + hasher->destroy(hasher); + chunk_free(&pubkey); + return TRUE; +} + +/** + * Encode the public key blob into subjectPublicKeyInfo. + */ +static bool build_pub_info(chunk_t *encoding, va_list args) +{ + chunk_t blob; + + if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER, &blob, + CRED_PART_END)) + { + *encoding = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), + asn1_bitstring("c", blob)); + return TRUE; + } + return FALSE; +} + +/** + * Build the fingerprint of the subjectPublicKeyInfo object. + */ +static bool build_info_sha1(chunk_t *encoding, va_list args) +{ + chunk_t pubkey; + + if (build_pub_info(&pubkey, args)) + { + return hash_pubkey(pubkey, encoding); + } + return FALSE; +} + +/** + * Build the fingerprint of the subjectPublicKey object. + */ +static bool build_sha1(chunk_t *encoding, va_list args) +{ + chunk_t blob; + + if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER, &blob, + CRED_PART_END)) + { + return hash_pubkey(chunk_clone(blob), encoding); + } + return FALSE; +} + +/** + * See header. + */ +bool tkm_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args) +{ + switch (type) + { + case KEYID_PUBKEY_INFO_SHA1: + return build_info_sha1(encoding, args); + case KEYID_PUBKEY_SHA1: + return build_sha1(encoding, args); + default: + return FALSE; + } +} diff --git a/src/charon-tkm/src/tkm/tkm_encoder.h b/src/charon-tkm/src/tkm/tkm_encoder.h new file mode 100644 index 000000000..e97e1e301 --- /dev/null +++ b/src/charon-tkm/src/tkm/tkm_encoder.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Reto Buerki + * Copyright (C) 2013 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 . + * + * 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_ENCODER_H_ +#define TKM_ENCODER_H_ + +#include + +/** + * Encoding function for TKM key fingerprints. + */ +bool tkm_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args); + +#endif /** TKM_ENCODER_H_ */ diff --git a/src/charon-tkm/src/tkm/tkm_public_key.c b/src/charon-tkm/src/tkm/tkm_public_key.c index d56f65269..e3f64ddba 100644 --- a/src/charon-tkm/src/tkm/tkm_public_key.c +++ b/src/charon-tkm/src/tkm/tkm_public_key.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2012 Reto Buerki - * Copyright (C) 2012 Adrian-Ken Rueegsegger + * Copyright (C) 2012-2013 Reto Buerki + * Copyright (C) 2012-2013 Adrian-Ken Rueegsegger * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,8 +14,6 @@ * for more details. */ -#include - #include "tkm_public_key.h" typedef struct private_tkm_public_key_t private_tkm_public_key_t; @@ -31,14 +29,9 @@ struct private_tkm_public_key_t { tkm_public_key_t public; /** - * Public modulus. + * ASN.1 blob of pubkey. */ - chunk_t n; - - /** - * Public exponent. - */ - chunk_t e; + chunk_t asn_blob; /** * Reference count. @@ -87,8 +80,7 @@ METHOD(public_key_t, get_fingerprint, bool, return TRUE; } return lib->encoding->encode(lib->encoding, type, this, fp, - CRED_PART_RSA_MODULUS, this->n, - CRED_PART_RSA_PUB_EXP, this->e, + CRED_PART_RSA_PUB_ASN1_DER, this->asn_blob, CRED_PART_END); } @@ -105,8 +97,7 @@ METHOD(public_key_t, destroy, void, if (ref_put(&this->ref)) { lib->encoding->clear_cache(lib->encoding, this); - chunk_free(&this->n); - chunk_free(&this->e); + chunk_free(&this->asn_blob); free(this); } } @@ -117,18 +108,14 @@ METHOD(public_key_t, destroy, void, tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args) { private_tkm_public_key_t *this; - chunk_t n, e; + chunk_t blob = chunk_empty; - n = e = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) { - case BUILD_RSA_MODULUS: - n = va_arg(args, chunk_t); - continue; - case BUILD_RSA_PUB_EXP: - e = va_arg(args, chunk_t); + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); continue; case BUILD_END: break; @@ -138,7 +125,7 @@ tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args) break; } - if (!e.ptr || !n.ptr) + if (!blob.ptr) { return NULL; } @@ -159,8 +146,7 @@ tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args) }, }, .ref = 1, - .n = chunk_clone(n), - .e = chunk_clone(e), + .asn_blob = chunk_clone(blob), ); return &this->public; -- cgit v1.2.3 From 0063e03325157ac9f92b6ba033341734aa9ad647 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Wed, 30 Jan 2013 15:36:03 +0100 Subject: Do not hardwire keys to KEY_RSA Make the TKM private and public keys more easily extendable by determining the associated key type dynamically. --- src/charon-tkm/src/tkm/tkm_private_key.c | 31 ++++++++++++++++++++++++++++--- src/charon-tkm/src/tkm/tkm_public_key.c | 24 ++++++++++++++++++++---- src/charon-tkm/src/tkm/tkm_public_key.h | 8 +++----- 3 files changed, 51 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_private_key.c b/src/charon-tkm/src/tkm/tkm_private_key.c index 616941454..9e3f96c95 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.c +++ b/src/charon-tkm/src/tkm/tkm_private_key.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2012 Reto Buerki - * Copyright (C) 2012 Adrian-Ken Rueegsegger + * Copyright (C) 2012-2013 Reto Buerki + * Copyright (C) 2012-2013 Adrian-Ken Rueegsegger * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -39,6 +39,11 @@ struct private_tkm_private_key_t { */ identification_t *id; + /** + * Key type. + */ + key_type_t key_type; + /** * Reference count. */ @@ -49,7 +54,7 @@ struct private_tkm_private_key_t { METHOD(private_key_t, get_type, key_type_t, private_tkm_private_key_t *this) { - return KEY_RSA; + return this->key_type; } METHOD(private_key_t, sign, bool, @@ -158,5 +163,25 @@ tkm_private_key_t *tkm_private_key_init(identification_t * const id) .id = id->clone(id), ); + /* get key type from associated public key */ + certificate_t *cert; + cert = lib->credmgr->get_cert(lib->credmgr, CERT_ANY, KEY_ANY, id, FALSE); + if (!cert) + { + destroy(this); + return NULL; + } + + public_key_t *pubkey = cert->get_public_key(cert); + if (!pubkey) + { + cert->destroy(cert); + destroy(this); + return NULL; + } + this->key_type = pubkey->get_type(pubkey); + pubkey->destroy(pubkey); + cert->destroy(cert); + return &this->public; } diff --git a/src/charon-tkm/src/tkm/tkm_public_key.c b/src/charon-tkm/src/tkm/tkm_public_key.c index e3f64ddba..9ebdc29e6 100644 --- a/src/charon-tkm/src/tkm/tkm_public_key.c +++ b/src/charon-tkm/src/tkm/tkm_public_key.c @@ -14,6 +14,8 @@ * for more details. */ +#include + #include "tkm_public_key.h" typedef struct private_tkm_public_key_t private_tkm_public_key_t; @@ -33,6 +35,11 @@ struct private_tkm_public_key_t { */ chunk_t asn_blob; + /** + * Key type. + */ + key_type_t key_type; + /** * Reference count. */ @@ -42,7 +49,7 @@ struct private_tkm_public_key_t { METHOD(public_key_t, get_type, key_type_t, private_tkm_public_key_t *this) { - return KEY_RSA; + return this->key_type; } METHOD(public_key_t, verify, bool, @@ -79,9 +86,17 @@ METHOD(public_key_t, get_fingerprint, bool, { return TRUE; } - return lib->encoding->encode(lib->encoding, type, this, fp, - CRED_PART_RSA_PUB_ASN1_DER, this->asn_blob, - CRED_PART_END); + switch(this->key_type) + { + case KEY_RSA: + return lib->encoding->encode(lib->encoding, type, this, fp, + CRED_PART_RSA_PUB_ASN1_DER, + this->asn_blob, CRED_PART_END); + default: + DBG1(DBG_LIB, "%N public key not supported, fingerprinting failed", + key_type_names, this->key_type); + return FALSE; + } } METHOD(public_key_t, get_ref, public_key_t*, @@ -147,6 +162,7 @@ tkm_public_key_t *tkm_public_key_load(key_type_t type, va_list args) }, .ref = 1, .asn_blob = chunk_clone(blob), + .key_type = type, ); return &this->public; diff --git a/src/charon-tkm/src/tkm/tkm_public_key.h b/src/charon-tkm/src/tkm/tkm_public_key.h index a469f7524..383c7dd4c 100644 --- a/src/charon-tkm/src/tkm/tkm_public_key.h +++ b/src/charon-tkm/src/tkm/tkm_public_key.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2012 Reto Buerki - * Copyright (C) 2012 Adrian-Ken Rueegsegger + * Copyright (C) 2012-2013 Reto Buerki + * Copyright (C) 2012-2013 Adrian-Ken Rueegsegger * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -35,9 +35,7 @@ struct tkm_public_key_t { /** * Load a TKM public key. * - * Accepts BUILD_RSA_* components. - * - * @param type type of the key, must be KEY_RSA + * @param type type of the key * @param args builder_part_t argument list * @return loaded key, NULL on failure */ -- cgit v1.2.3 From 7f21523abd0775b0d515b526b4f2d12bf1d4b7de Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Wed, 30 Jan 2013 11:16:16 +0100 Subject: Add charon-tkm API documentation --- src/charon-tkm/src/ees/ees_callbacks.h | 12 ++++++- src/charon-tkm/src/ehandler/eh_callbacks.h | 11 +++++- src/charon-tkm/src/tkm/tkm.h | 55 ++++++++++++++++++++++++++++- src/charon-tkm/src/tkm/tkm_chunk_map.h | 7 +++- src/charon-tkm/src/tkm/tkm_cred.h | 7 +++- src/charon-tkm/src/tkm/tkm_diffie_hellman.h | 7 +++- src/charon-tkm/src/tkm/tkm_encoder.h | 7 +++- src/charon-tkm/src/tkm/tkm_id_manager.h | 7 +++- src/charon-tkm/src/tkm/tkm_kernel_ipsec.h | 7 +++- src/charon-tkm/src/tkm/tkm_kernel_sad.h | 7 +++- src/charon-tkm/src/tkm/tkm_keymat.h | 7 +++- src/charon-tkm/src/tkm/tkm_listener.h | 7 +++- src/charon-tkm/src/tkm/tkm_nonceg.h | 7 +++- src/charon-tkm/src/tkm/tkm_private_key.h | 7 +++- src/charon-tkm/src/tkm/tkm_public_key.h | 5 +++ src/charon-tkm/src/tkm/tkm_types.h | 7 +++- src/charon-tkm/src/tkm/tkm_utils.h | 7 +++- 17 files changed, 158 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/ees/ees_callbacks.h b/src/charon-tkm/src/ees/ees_callbacks.h index f8598f238..b73dc6cb5 100644 --- a/src/charon-tkm/src/ees/ees_callbacks.h +++ b/src/charon-tkm/src/ees/ees_callbacks.h @@ -14,6 +14,16 @@ * for more details. */ +/** + * @defgroup tkm-eescallbacks ees callbacks + * @{ @ingroup tkm + * + * ESP SA Event Service (EES) callbacks. + * The xfrm-proxy forwards acquire and expire events from the kernel to + * charon-tkm using the EES interface. Upon reception of an event the + * corresponding callback is executed. + */ + #ifndef EES_CALLBACKS_H_ #define EES_CALLBACKS_H_ @@ -29,4 +39,4 @@ void charon_esa_expire(result_type *res, const sp_id_type sp_id, const esp_spi_type spi_rem, const protocol_type protocol, const expiry_flag_type hard); -#endif /** EES_CALLBACKS_H_ */ +#endif /** EES_CALLBACKS_H_ @}*/ diff --git a/src/charon-tkm/src/ehandler/eh_callbacks.h b/src/charon-tkm/src/ehandler/eh_callbacks.h index 1be924913..db325dcd2 100644 --- a/src/charon-tkm/src/ehandler/eh_callbacks.h +++ b/src/charon-tkm/src/ehandler/eh_callbacks.h @@ -14,6 +14,15 @@ * for more details. */ +/** + * @defgroup tkm-ehandler exception handler + * @{ @ingroup tkm + * + * The exception handler callback is registered as global exception action in + * the Ada runtime. If an exception is raised in Ada code this callback is + * executed. + */ + #ifndef EH_CALLBACKS_H_ #define EH_CALLBACKS_H_ @@ -22,4 +31,4 @@ */ void charon_terminate(char *msg); -#endif /** EH_CALLBACKS_H_ */ +#endif /** EH_CALLBACKS_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm.h b/src/charon-tkm/src/tkm/tkm.h index 9d559d9fc..7c711312b 100644 --- a/src/charon-tkm/src/tkm/tkm.h +++ b/src/charon-tkm/src/tkm/tkm.h @@ -14,6 +14,59 @@ * for more details. */ +/** + * @defgroup tkm tkm + * + * @addtogroup tkm + * @{ + * + * Untrusted IKEv2 component used with Trusted Key Manager for IKE + * disaggregation. + * + * The untrusted IKEv2 component used in conjunction with the Trusted Key + * Manager infrastructure is implemented as a separate charon instance located + * in its own directory below the strongSwan top-level source directory + * (src/charon-tkm). This has the advantage that the TKM code is contained and + * does not mix with other strongSwan files. The charon-tkm binary startup code + * is modeled after the charon-nm instance, a special charon daemon variant to + * be used with the GNOME NetworkManager project. The major difference is the + * registration of custom TKM plugins as the final step of the startup phase. + * The charon-tkm daemon does not rely on the dynamic plugin loading mechanism + * for its core plugins, they are statically registered before entering the main + * processing loop. + * + * The following diagram shows the main components of the system and how they + * communicate. + @verbatim + + +------------+ +------------+ +------------+ + | xfrm-proxy |<-[tkm-rpc->| charon-tkm |<-[tkm-rpc]->| TKM | + +------------+ +------------+ +------------+ + ^ ^ + [Netlink | XFRM] [XFRM | Netlink] + | v + +-----------------------------------------------------------------+ + | Kernel | + +-----------------------------------------------------------------+ + + @endverbatim + * Since the charon-tkm code uses the tkm-rpc library written in Ada, the daemon + * has to be built using an Ada-aware toolchain. The integration of Ada code + * into the strongSwan codebase is explained in the TKM documentation, section + * 5.4.1: http://www.codelabs.ch/tkm#anchor-doc. + * + * The Trusted Key Manager (TKM) is a minimal Trusted Computing Base which + * implements security-critical functions of the IKEv2 protocol. + * + * The xfrm-proxy receives XFRM Acquire and Expiry events from the kernel and + * forwards them to the charon-tkm IKE daemon for further processing. + * + * The underlying concept of IKE disaggregation and the design of TKM and all + * related components, of which charon-tkm is one component, is presented in + * detail in the project documentation found at + * http://www.codelabs.ch/tkm#anchor-doc. + */ + #ifndef TKM_H_ #define TKM_H_ @@ -57,4 +110,4 @@ void tkm_deinit(); */ extern tkm_t *tkm; -#endif /** TKM_H_ */ +#endif /** TKM_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_chunk_map.h b/src/charon-tkm/src/tkm/tkm_chunk_map.h index 746de7d4b..2d8ea8f76 100644 --- a/src/charon-tkm/src/tkm/tkm_chunk_map.h +++ b/src/charon-tkm/src/tkm/tkm_chunk_map.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-chunk-map chunk map + * @{ @ingroup tkm + */ + #ifndef TKM_CHUNK_MAP_H_ #define TKM_CHUNK_MAP_H_ @@ -64,4 +69,4 @@ struct tkm_chunk_map_t { */ tkm_chunk_map_t *tkm_chunk_map_create(); -#endif /** TKM_CHUNK_MAP_H_ */ +#endif /** TKM_CHUNK_MAP_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_cred.h b/src/charon-tkm/src/tkm/tkm_cred.h index 362e228c8..1cfb5b9c7 100644 --- a/src/charon-tkm/src/tkm/tkm_cred.h +++ b/src/charon-tkm/src/tkm/tkm_cred.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-credential credential set + * @{ @ingroup tkm + */ + #ifndef TKM_CRED_H_ #define TKM_CRED_H_ @@ -43,4 +48,4 @@ struct tkm_cred_t { */ tkm_cred_t *tkm_cred_create(); -#endif /** TKM_CRED_H_ */ +#endif /** TKM_CRED_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.h b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h index 0f457931a..a144303fa 100644 --- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.h +++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-dh diffie hellman + * @{ @ingroup tkm + */ + #ifndef TKM_DIFFIE_HELLMAN_H_ #define TKM_DIFFIE_HELLMAN_H_ @@ -49,4 +54,4 @@ struct tkm_diffie_hellman_t { */ tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group); -#endif /** TKM_DIFFIE_HELLMAN_H_ */ +#endif /** TKM_DIFFIE_HELLMAN_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_encoder.h b/src/charon-tkm/src/tkm/tkm_encoder.h index e97e1e301..7c6a4989d 100644 --- a/src/charon-tkm/src/tkm/tkm_encoder.h +++ b/src/charon-tkm/src/tkm/tkm_encoder.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-credential-enc credential encoder + * @{ @ingroup tkm + */ + #ifndef TKM_ENCODER_H_ #define TKM_ENCODER_H_ @@ -25,4 +30,4 @@ bool tkm_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, va_list args); -#endif /** TKM_ENCODER_H_ */ +#endif /** TKM_ENCODER_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.h b/src/charon-tkm/src/tkm/tkm_id_manager.h index b1c1160a0..0fc9ff8ef 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.h +++ b/src/charon-tkm/src/tkm/tkm_id_manager.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-id-manager id manager + * @{ @ingroup tkm + */ + #ifndef TKM_ID_MANAGER_H_ #define TKM_ID_MANAGER_H_ @@ -91,4 +96,4 @@ struct tkm_id_manager_t { */ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits); -#endif /** TKM_ID_MANAGER_H_ */ +#endif /** TKM_ID_MANAGER_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h index bb30d1c61..14db21266 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-kernel-ipsec kernel ipsec + * @{ @ingroup tkm + */ + #ifndef TKM_KERNEL_IPSEC_H_ #define TKM_KERNEL_IPSEC_H_ @@ -39,4 +44,4 @@ struct tkm_kernel_ipsec_t { */ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create(); -#endif /** TKM_KERNEL_IPSEC_H_ */ +#endif /** TKM_KERNEL_IPSEC_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.h b/src/charon-tkm/src/tkm/tkm_kernel_sad.h index 6863584f4..0194cd3bc 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_sad.h +++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-kernel-sad kernel sad + * @{ @ingroup tkm + */ + #ifndef TKM_KERNEL_SAD_H_ #define TKM_KERNEL_SAD_H_ @@ -75,4 +80,4 @@ struct tkm_kernel_sad_t { */ tkm_kernel_sad_t *tkm_kernel_sad_create(); -#endif /** TKM_KERNEL_SAD_H_ */ +#endif /** TKM_KERNEL_SAD_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index 207f9728e..ee90bead5 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-keymat keymat + * @{ @ingroup tkm + */ + #ifndef TKM_KEYMAT_H_ #define TKM_KEYMAT_H_ @@ -69,4 +74,4 @@ struct tkm_keymat_t { */ tkm_keymat_t *tkm_keymat_create(bool initiator); -#endif /** KEYMAT_TKM_H_ */ +#endif /** KEYMAT_TKM_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_listener.h b/src/charon-tkm/src/tkm/tkm_listener.h index 262d66e33..1162a77be 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.h +++ b/src/charon-tkm/src/tkm/tkm_listener.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-listener listener + * @{ @ingroup tkm + */ + #ifndef TKM_LISTENER_H_ #define TKM_LISTENER_H_ @@ -44,4 +49,4 @@ struct tkm_listener_t { */ tkm_listener_t *tkm_listener_create(); -#endif /** TKM_LISTENER_H_ */ +#endif /** TKM_LISTENER_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.h b/src/charon-tkm/src/tkm/tkm_nonceg.h index 25ec48a64..ceadb081f 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.h +++ b/src/charon-tkm/src/tkm/tkm_nonceg.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-nonceg nonce generator + * @{ @ingroup tkm + */ + #ifndef TKM_NONCEG_H_ #define TKM_NONCEG_H_ @@ -48,4 +53,4 @@ struct tkm_nonceg_t { */ tkm_nonceg_t *tkm_nonceg_create(); -#endif /** TKM_NONCEG_H_ */ +#endif /** TKM_NONCEG_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_private_key.h b/src/charon-tkm/src/tkm/tkm_private_key.h index 343752f28..ded8300ca 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.h +++ b/src/charon-tkm/src/tkm/tkm_private_key.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-privkey private key + * @{ @ingroup tkm + */ + #ifndef TKM_PRIVATE_KEY_H_ #define TKM_PRIVATE_KEY_H_ @@ -37,4 +42,4 @@ struct tkm_private_key_t { */ tkm_private_key_t *tkm_private_key_init(identification_t * const id); -#endif /** TKM_PRIVATE_KEY_H_ */ +#endif /** TKM_PRIVATE_KEY_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_public_key.h b/src/charon-tkm/src/tkm/tkm_public_key.h index 383c7dd4c..5b21287b7 100644 --- a/src/charon-tkm/src/tkm/tkm_public_key.h +++ b/src/charon-tkm/src/tkm/tkm_public_key.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-pubkey public key + * @{ @ingroup tkm + */ + #ifndef TKM_PUBLIC_KEY_H_ #define TKM_PUBLIC_KEY_H_ diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index 96a3bb273..cef53deb3 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-types types + * @{ @ingroup tkm + */ + #ifndef TKM_TYPES_H_ #define TKM_TYPES_H_ @@ -120,4 +125,4 @@ struct sign_info_t { }; -#endif /** TKM_TYPES_H_ */ +#endif /** TKM_TYPES_H_ @}*/ diff --git a/src/charon-tkm/src/tkm/tkm_utils.h b/src/charon-tkm/src/tkm/tkm_utils.h index 37a2c7ce5..ac8fac742 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.h +++ b/src/charon-tkm/src/tkm/tkm_utils.h @@ -14,6 +14,11 @@ * for more details. */ +/** + * @defgroup tkm-utils utils + * @{ @ingroup tkm + */ + #ifndef TKM_UTILS_H_ #define TKM_UTILS_H_ @@ -40,4 +45,4 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, void chunk_to_sequence(const chunk_t * const chunk, void *sequence, const uint32_t typelen); -#endif /** TKM_UTILS_H_ */ +#endif /** TKM_UTILS_H_ @}*/ -- cgit v1.2.3 From e2928a3e8c277483833b93bbd4ee2412a30edc82 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 11 Feb 2013 15:21:49 +0100 Subject: Provide MODP-2048 through TKM DH plugin --- src/charon-tkm/src/charon-tkm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 988541e36..0b39058a6 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -289,6 +289,7 @@ int main(int argc, char *argv[]) PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create), PLUGIN_PROVIDE(NONCE_GEN), PLUGIN_REGISTER(DH, tkm_diffie_hellman_create), + PLUGIN_PROVIDE(DH, MODP_2048_BIT), PLUGIN_PROVIDE(DH, MODP_3072_BIT), PLUGIN_PROVIDE(DH, MODP_4096_BIT), PLUGIN_REGISTER(PUBKEY, tkm_public_key_load, TRUE), -- cgit v1.2.3 From c57b7a66c30e7c9c5484818bb5b2c6a7779838e2 Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 4 Mar 2013 11:23:22 +0100 Subject: Use network byte order for ESA SPIs --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 734bec73c..7d14ba702 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -149,8 +149,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, */ if (nonce_loc_id == 0 && esa.dh_id == 0) { - if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, ntohl(spi_loc), - ntohl(spi_rem)) != TKM_OK) + if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, spi_loc, spi_rem) + != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id); goto failure; @@ -162,8 +162,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id, - nc_rem, initiator, ntohl(spi_loc), - ntohl(spi_rem)) != TKM_OK) + nc_rem, initiator, spi_loc, spi_rem) + != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id); goto failure; @@ -176,8 +176,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id, - nc_rem, initiator, ntohl(spi_loc), - ntohl(spi_rem)) != TKM_OK) + nc_rem, initiator, spi_loc, spi_rem) != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id); goto failure; -- cgit v1.2.3 From 7cc6fa1a983a668bd884e08f0e453637d4702cbe Mon Sep 17 00:00:00 2001 From: Adrian-Ken Rueegsegger Date: Mon, 18 Mar 2013 18:47:16 +0100 Subject: Various stylistic fixes --- src/charon-tkm/src/tkm/tkm.c | 27 ++++------ src/charon-tkm/src/tkm/tkm_chunk_map.h | 2 +- src/charon-tkm/src/tkm/tkm_cred.c | 6 ++- src/charon-tkm/src/tkm/tkm_id_manager.c | 12 ++--- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 40 ++++++++------- src/charon-tkm/src/tkm/tkm_kernel_sad.c | 13 +++-- src/charon-tkm/src/tkm/tkm_keymat.c | 70 +++++++++++++------------ src/charon-tkm/src/tkm/tkm_listener.c | 85 +++++++++++++++++++------------ src/charon-tkm/src/tkm/tkm_nonceg.c | 1 + src/charon-tkm/src/tkm/tkm_private_key.c | 11 ++-- src/charon-tkm/src/tkm/tkm_utils.c | 7 +-- src/charon-tkm/src/tkm/tkm_utils.h | 4 +- 12 files changed, 155 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/charon-tkm/src/tkm/tkm.c b/src/charon-tkm/src/tkm/tkm.c index 9cf54b087..a39221dc2 100644 --- a/src/charon-tkm/src/tkm/tkm.c +++ b/src/charon-tkm/src/tkm/tkm.c @@ -52,23 +52,16 @@ tkm_t *tkm = NULL; bool tkm_init() { private_tkm_t *this; - active_requests_type max_requests; - nc_id_type nc; - dh_id_type dh; - cc_id_type cc; - ae_id_type ae; - isa_id_type isa; - esa_id_type esa; + char *ikesock, *eessock; + tkm_limits_t limits; /* initialize TKM client library */ tkmlib_init(); ehandler_init(); - const char * const ikesock = lib->settings->get_str(lib->settings, - "%s.ike_socket", - IKE_SOCKET, - charon->name); + ikesock = lib->settings->get_str(lib->settings, "%s.ike_socket", IKE_SOCKET, + charon->name); if (ike_init(ikesock) != TKM_OK) { tkmlib_final(); @@ -76,10 +69,8 @@ bool tkm_init() } DBG1(DBG_DMN, "connected to TKM via socket '%s'", ikesock); - const char * const eessock = lib->settings->get_str(lib->settings, - "%s.ees_socket", - EES_SOCKET, - charon->name); + eessock = lib->settings->get_str(lib->settings, "%s.ees_socket", EES_SOCKET, + charon->name); ees_server_init(eessock); DBG1(DBG_DMN, "serving EES requests on socket '%s'", eessock); @@ -91,15 +82,15 @@ bool tkm_init() } /* get limits from tkm */ - if (ike_tkm_limits(&max_requests, &nc, &dh, &cc, &ae, &isa, &esa) != TKM_OK) + if (ike_tkm_limits(&max_requests, &limits[TKM_CTX_NONCE], &limits[TKM_CTX_DH], + &limits[TKM_CTX_CC], &limits[TKM_CTX_AE], + &limits[TKM_CTX_ISA], &limits[TKM_CTX_ESA]) != TKM_OK) { ees_server_finalize(); tkmlib_final(); return FALSE; } - const tkm_limits_t limits = {nc, dh, cc, isa, ae, esa}; - INIT(this, .public = { .idmgr = tkm_id_manager_create(limits), diff --git a/src/charon-tkm/src/tkm/tkm_chunk_map.h b/src/charon-tkm/src/tkm/tkm_chunk_map.h index 2d8ea8f76..648257574 100644 --- a/src/charon-tkm/src/tkm/tkm_chunk_map.h +++ b/src/charon-tkm/src/tkm/tkm_chunk_map.h @@ -39,7 +39,7 @@ struct tkm_chunk_map_t { * @param id id associated with data */ void (*insert)(tkm_chunk_map_t * const this, const chunk_t * const data, - const uint64_t id); + const uint64_t id); /** * Get id for given chunk. diff --git a/src/charon-tkm/src/tkm/tkm_cred.c b/src/charon-tkm/src/tkm/tkm_cred.c index cf591d4e3..d9517f908 100644 --- a/src/charon-tkm/src/tkm/tkm_cred.c +++ b/src/charon-tkm/src/tkm/tkm_cred.c @@ -54,20 +54,22 @@ struct private_tkm_cred_t { METHOD(credential_set_t, create_private_enumerator, enumerator_t*, private_tkm_cred_t *this, key_type_t type, identification_t *id) { + identification_t *entry; + if (!id) { return this->known_keys->create_enumerator(this->known_keys); } - identification_t *entry; this->lock->write_lock(this->lock); entry = this->known_keys->get(this->known_keys, id); if (!entry) { identification_t *clone = id->clone(id); - DBG1(DBG_CFG, "adding private key proxy for id '%Y'", clone); tkm_private_key_t *key = tkm_private_key_init(id); + + DBG1(DBG_CFG, "adding private key proxy for id '%Y'", clone); if (!key) { DBG1(DBG_CFG, "unable to create private key for id '%Y'", clone); diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c index 63377e65d..407d0a87f 100644 --- a/src/charon-tkm/src/tkm/tkm_id_manager.c +++ b/src/charon-tkm/src/tkm/tkm_id_manager.c @@ -81,7 +81,7 @@ METHOD(tkm_id_manager_t, acquire_id, int, if (!is_valid_kind(kind)) { DBG1(DBG_LIB, "tried to acquire id for invalid context kind '%d'", - kind); + kind); return 0; } @@ -99,8 +99,8 @@ METHOD(tkm_id_manager_t, acquire_id, int, if (!id) { - DBG1(DBG_LIB, "acquiring %N context id failed", - tkm_context_kind_names, kind); + DBG1(DBG_LIB, "acquiring %N context id failed", tkm_context_kind_names, + kind); } return id; @@ -115,7 +115,7 @@ METHOD(tkm_id_manager_t, release_id, bool, if (!is_valid_kind(kind)) { DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'", - id, kind); + id, kind); return FALSE; } @@ -160,8 +160,8 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits) this->limits[i] = limits[i]; this->ctxids[i] = calloc(limits[i], sizeof(bool)); this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); - DBG2(DBG_LIB, "%N initialized, %llu slot(s)", - tkm_context_kind_names, i, limits[i]); + DBG2(DBG_LIB, "%N initialized, %llu slot(s)", tkm_context_kind_names, i, + limits[i]); } return &this->public; diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 7d14ba702..69aefea97 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -62,6 +62,8 @@ METHOD(kernel_ipsec_t, get_spi, status_t, private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) { + bool result; + if (!this->rng) { this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); @@ -73,8 +75,8 @@ METHOD(kernel_ipsec_t, get_spi, status_t, } DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid); - const bool result = this->rng->get_bytes(this->rng, sizeof(u_int32_t), - (u_int8_t *)spi); + result = this->rng->get_bytes(this->rng, sizeof(u_int32_t), + (u_int8_t *)spi); return result ? SUCCESS : FAILED; } @@ -93,12 +95,21 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int16_t cpi, bool encap, bool esn, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) { + esa_info_t esa; + bool initiator; + esp_spi_type spi_loc, spi_rem; + host_t *local, *peer; + chunk_t *nonce_loc, *nonce_rem; + nc_id_type nonce_loc_id; + esa_id_type esa_id; + nonce_type nc_rem; + if (enc_key.ptr == NULL) { DBG1(DBG_KNL, "Unable to get ESA information"); return FAILED; } - esa_info_t esa = *(esa_info_t *)(enc_key.ptr); + esa = *(esa_info_t *)(enc_key.ptr); /* only handle the case where we have both distinct ESP spi's available */ if (esa.spi_r == spi) @@ -109,11 +120,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, } /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */ - const bool initiator = esa.is_encr_r && inbound; - - esp_spi_type spi_loc, spi_rem; - host_t *local, *peer; - chunk_t *nonce_loc, *nonce_rem; + initiator = esa.is_encr_r && inbound; if (initiator) { spi_loc = spi; @@ -133,10 +140,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, nonce_rem = &esa.nonce_i; } - const nc_id_type nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, - nonce_loc); - - const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); + esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA); if (!this->sad->insert(this->sad, esa_id, peer, local, spi_loc, protocol)) { DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id); @@ -147,6 +151,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, * creation of first CHILD SA: * no nonce and no dh contexts because the ones from the IKE SA are re-used */ + nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce_loc); if (nonce_loc_id == 0 && esa.dh_id == 0) { if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, spi_loc, spi_rem) @@ -159,7 +164,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, /* creation of child SA without PFS: no dh context */ else if (nonce_loc_id != 0 && esa.dh_id == 0) { - nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id, nc_rem, initiator, spi_loc, spi_rem) @@ -173,7 +177,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, /* creation of subsequent child SA with PFS: nonce and dh context are set */ else { - nonce_type nc_rem; chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id, nc_rem, initiator, spi_loc, spi_rem) != TKM_OK) @@ -222,8 +225,9 @@ METHOD(kernel_ipsec_t, del_sa, status_t, private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) { - const esa_id_type esa_id = this->sad->get_esa_id(this->sad, src, dst, spi, - protocol); + esa_id_type esa_id; + + esa_id = this->sad->get_esa_id(this->sad, src, dst, spi, protocol); if (esa_id) { DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id, @@ -314,14 +318,14 @@ METHOD(kernel_ipsec_t, bypass_socket, bool, if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) { DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", - strerror(errno)); + strerror(errno)); return FALSE; } policy.dir = XFRM_POLICY_IN; if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) { DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", - strerror(errno)); + strerror(errno)); return FALSE; } return TRUE; diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.c b/src/charon-tkm/src/tkm/tkm_kernel_sad.c index 02b6ddc7c..360a47bdc 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_sad.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.c @@ -129,8 +129,9 @@ METHOD(tkm_kernel_sad_t, insert, bool, const host_t * const src, const host_t * const dst, const u_int32_t spi, const u_int8_t proto) { - + status_t result; sad_entry_t *new_entry; + INIT(new_entry, .esa_id = esa_id, .src = (host_t *)src, @@ -140,9 +141,9 @@ METHOD(tkm_kernel_sad_t, insert, bool, ); this->mutex->lock(this->mutex); - const status_t result = this->data->find_first(this->data, - (linked_list_match_t)sad_entry_equal, - NULL, new_entry); + result = this->data->find_first(this->data, + (linked_list_match_t)sad_entry_equal, NULL, + new_entry); if (result == NOT_FOUND) { DBG3(DBG_KNL, "inserting SAD entry (esa: %llu, src: %H, dst: %H, " @@ -192,8 +193,10 @@ METHOD(tkm_kernel_sad_t, _remove, bool, { sad_entry_t *current; bool removed = FALSE; + enumerator_t *enumerator; + this->mutex->lock(this->mutex); - enumerator_t *enumerator = this->data->create_enumerator(this->data); + enumerator = this->data->create_enumerator(this->data); while (enumerator->enumerate(enumerator, (void **)¤t)) { if (current->esa_id == esa_id) diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index fe4caf9ec..772fac8b0 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -94,9 +94,11 @@ static void aead_create_from_keys(aead_t **in, aead_t **out, const u_int16_t key_size, bool initiator) { *in = *out = NULL; + signer_t *signer_i, *signer_r; + crypter_t *crypter_i, *crypter_r; - signer_t * const signer_i = lib->crypto->create_signer(lib->crypto, int_alg); - signer_t * const signer_r = lib->crypto->create_signer(lib->crypto, int_alg); + signer_i = lib->crypto->create_signer(lib->crypto, int_alg); + signer_r = lib->crypto->create_signer(lib->crypto, int_alg); if (signer_i == NULL || signer_r == NULL) { DBG1(DBG_IKE, "%N %N not supported!", @@ -104,10 +106,8 @@ static void aead_create_from_keys(aead_t **in, aead_t **out, integrity_algorithm_names, int_alg); return; } - crypter_t * const crypter_i = lib->crypto->create_crypter(lib->crypto, - enc_alg, key_size); - crypter_t * const crypter_r = lib->crypto->create_crypter(lib->crypto, - enc_alg, key_size); + crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, key_size); + crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, key_size); if (crypter_i == NULL || crypter_r == NULL) { signer_i->destroy(signer_i); @@ -174,41 +174,50 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { - /* Check encryption and integrity algorithms */ u_int16_t enc_alg, int_alg, key_size; - if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &key_size)) + u_int64_t nc_id, spi_loc, spi_rem; + chunk_t *nonce, c_ai, c_ar, c_ei, c_er; + tkm_diffie_hellman_t *tkm_dh; + dh_id_type dh_id; + nonce_type nonce_rem; + result_type res; + key_type sk_ai, sk_ar, sk_ei, sk_er; + + /* Check encryption and integrity algorithms */ + if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, + &key_size)) { DBG1(DBG_IKE, "no %N selected", transform_type_names, - ENCRYPTION_ALGORITHM); + ENCRYPTION_ALGORITHM); return FALSE; } if (encryption_algorithm_is_aead(enc_alg)) { DBG1(DBG_IKE, "AEAD algorithm %N not supported", - encryption_algorithm_names, enc_alg); + encryption_algorithm_names, enc_alg); return FALSE; } if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, NULL)) { DBG1(DBG_IKE, "no %N selected", transform_type_names, - INTEGRITY_ALGORITHM); + INTEGRITY_ALGORITHM); return FALSE; } if (!(enc_alg == ENCR_AES_CBC && key_size == 256 && - int_alg == AUTH_HMAC_SHA2_512_256)) + int_alg == AUTH_HMAC_SHA2_512_256)) { - DBG1(DBG_IKE, "the TKM only supports aes256-sha512 at the moment, please" - " update your configuration"); + DBG1(DBG_IKE, "the TKM only supports aes256-sha512 at the moment, " + "please update your configuration"); return FALSE; } DBG2(DBG_IKE, "using %N for encryption, %N for integrity", - encryption_algorithm_names, enc_alg, - integrity_algorithm_names, int_alg); + encryption_algorithm_names, enc_alg, integrity_algorithm_names, + int_alg); /* Acquire nonce context id */ - chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r; - const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); + nonce = this->initiator ? &nonce_i : &nonce_r; + nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce); if (!nc_id) { DBG1(DBG_IKE, "unable to acquire context id for nonce"); @@ -216,11 +225,8 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, } /* Get DH context id */ - tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh; - const dh_id_type dh_id = tkm_dh->get_id(tkm_dh); - - nonce_type nonce_rem; - u_int64_t spi_loc, spi_rem; + tkm_dh = (tkm_diffie_hellman_t *)dh; + dh_id = tkm_dh->get_id(tkm_dh); if (this->initiator) { @@ -235,8 +241,6 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, spi_rem = id->get_initiator_spi(id); } - result_type res; - key_type sk_ai, sk_ar, sk_ei, sk_er; if (rekey_function == PRF_UNDEFINED) { this->ae_ctx_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_AE); @@ -253,12 +257,14 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, } else { + isa_info_t isa_info; + if (rekey_skd.ptr == NULL || rekey_skd.len != sizeof(isa_info_t)) { DBG1(DBG_IKE, "unable to retrieve parent isa info"); return FALSE; } - const isa_info_t isa_info = *((isa_info_t *)(rekey_skd.ptr)); + isa_info = *((isa_info_t *)(rekey_skd.ptr)); DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, nc: %llu," "dh: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, isa_info.ae_id, nc_id, dh_id, spi_loc, spi_rem); @@ -276,15 +282,14 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, return FALSE; } - chunk_t c_ai, c_ar, c_ei, c_er; sequence_to_chunk(sk_ai.data, sk_ai.size, &c_ai); sequence_to_chunk(sk_ar.data, sk_ar.size, &c_ar); sequence_to_chunk(sk_ei.data, sk_ei.size, &c_ei); sequence_to_chunk(sk_er.data, sk_er.size, &c_er); - aead_create_from_keys(&this->aead_in, &this->aead_out, - &c_ai, &c_ar, &c_ei, &c_er, - enc_alg, int_alg, key_size / 8, this->initiator); + aead_create_from_keys(&this->aead_in, &this->aead_out, &c_ai, &c_ar, &c_ei, + &c_er, enc_alg, int_alg, key_size / 8, + this->initiator); chunk_clear(&c_ai); chunk_clear(&c_ar); @@ -315,8 +320,8 @@ METHOD(keymat_v2_t, derive_child_keys, bool, chunk_t *encr_r, chunk_t *integ_r) { esa_info_t *esa_info_i, *esa_info_r; - dh_id_type dh_id = 0; + if (dh) { dh_id = ((tkm_diffie_hellman_t *)dh)->get_id((tkm_diffie_hellman_t *)dh); @@ -362,6 +367,8 @@ METHOD(keymat_v2_t, get_auth_octets, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets) { + sign_info_t *sign; + if (verify) { /* store peer init message for authentication step */ @@ -370,7 +377,6 @@ METHOD(keymat_v2_t, get_auth_octets, bool, return TRUE; } - sign_info_t *sign; INIT(sign, .isa_id = this->isa_ctx_id, .init_message = chunk_clone(ike_sa_init), diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 47cfef5ac..050586456 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -56,7 +56,9 @@ static ri_id_type get_remote_identity_id(peer_cfg_t *peer) { ri_id_type remote_id = 0; child_cfg_t *child; - enumerator_t* children = peer->create_child_cfg_enumerator(peer); + enumerator_t* children; + + children = peer->create_child_cfg_enumerator(peer); /* pick the reqid of the first child, no need to enumerate all children. */ children->enumerate(children, &child); @@ -76,20 +78,26 @@ static ri_id_type get_remote_identity_id(peer_cfg_t *peer) */ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) { - DBG1(DBG_IKE, "building certificate chain context %llu for IKE SA %s", - cc_id, ike_sa->get_name((ike_sa_t *)ike_sa)); - auth_cfg_t *auth; certificate_t *cert; enumerator_t *rounds; + + DBG1(DBG_IKE, "building certificate chain context %llu for IKE SA %s", + cc_id, ike_sa->get_name((ike_sa_t *)ike_sa)); + rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE); while (rounds->enumerate(rounds, &auth)) { cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); if (cert) { - /* set user certificate */ chunk_t enc_user_cert; + ri_id_type ri_id; + certificate_type user_cert; + auth_rule_t rule; + enumerator_t *enumerator; + + /* set user certificate */ if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert)) { DBG1(DBG_IKE, "unable to extract encoded user certificate"); @@ -97,10 +105,8 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) return FALSE; } - ri_id_type ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa)); - certificate_type user_cert; - chunk_to_sequence(&enc_user_cert, &user_cert, - sizeof(certificate_type)); + ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa)); + chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type)); chunk_free(&enc_user_cert); if (ike_cc_set_user_certificate(cc_id, ri_id, 1, user_cert) != TKM_OK) { @@ -111,23 +117,23 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) } /* process intermediate CA certificates */ - auth_rule_t rule; - enumerator_t *enumerator = auth->create_enumerator(auth); + enumerator = auth->create_enumerator(auth); while (enumerator->enumerate(enumerator, &rule, &cert)) { if (rule == AUTH_RULE_IM_CERT) { chunk_t enc_im_cert; + certificate_type im_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert)) { DBG1(DBG_IKE, "unable to extract encoded intermediate CA" - " certificate"); + " certificate"); rounds->destroy(rounds); enumerator->destroy(enumerator); return FALSE; } - certificate_type im_cert; chunk_to_sequence(&enc_im_cert, &im_cert, sizeof(certificate_type)); chunk_free(&enc_im_cert); @@ -147,7 +153,10 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) cert = auth->get(auth, AUTH_RULE_CA_CERT); if (cert) { + const ca_id_type ca_id = 1; + certificate_type ca_cert; chunk_t enc_ca_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert)) { DBG1(DBG_IKE, "unable to extract encoded CA certificate"); @@ -155,8 +164,6 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) return FALSE; } - const ca_id_type ca_id = 1; - certificate_type ca_cert; chunk_to_sequence(&enc_ca_cert, &ca_cert, sizeof(certificate_type)); chunk_free(&enc_ca_cert); @@ -200,8 +207,12 @@ METHOD(listener_t, alert, bool, { if (alert == ALERT_KEEP_ON_CHILD_SA_FAILURE) { - tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); - const isa_id_type isa_id = keymat->get_isa_id(keymat); + tkm_keymat_t *keymat; + isa_id_type isa_id; + + keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + isa_id = keymat->get_isa_id(keymat); + DBG1(DBG_IKE, "TKM alert listener called for ISA context %llu", isa_id); if (ike_isa_skip_create_first(isa_id) != TKM_OK) { @@ -217,47 +228,51 @@ METHOD(listener_t, authorize, bool, private_tkm_listener_t *this, ike_sa_t *ike_sa, bool final, bool *success) { + tkm_keymat_t *keymat; + isa_id_type isa_id; + cc_id_type cc_id; + chunk_t *auth, *other_init_msg; + signature_type signature; + init_message_type init_msg; + if (!final) { return TRUE; } - tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); - const isa_id_type isa_id = keymat->get_isa_id(keymat); + keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + isa_id = keymat->get_isa_id(keymat); DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id); - const cc_id_type cc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_CC); + cc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_CC); if (!cc_id) { DBG1(DBG_IKE, "unable to acquire CC context id"); *success = FALSE; return TRUE; } - const bool cc_success = build_cert_chain(ike_sa, cc_id); - if (!cc_success) + if (!build_cert_chain(ike_sa, cc_id)) { DBG1(DBG_IKE, "unable to build certificate chain"); *success = FALSE; return TRUE; } - const chunk_t * const auth = keymat->get_auth_payload(keymat); + auth = keymat->get_auth_payload(keymat); if (!auth->ptr) { DBG1(DBG_IKE, "no AUTHENTICATION data available"); *success = FALSE; } - const chunk_t * const other_init_msg = keymat->get_peer_init_msg(keymat); + other_init_msg = keymat->get_peer_init_msg(keymat); if (!other_init_msg->ptr) { DBG1(DBG_IKE, "no peer init message available"); *success = FALSE; } - signature_type signature; chunk_to_sequence(auth, &signature, sizeof(signature_type)); - init_message_type init_msg; chunk_to_sequence(other_init_msg, &init_msg, sizeof(init_message_type)); if (ike_isa_auth(isa_id, cc_id, init_msg, signature) != TKM_OK) @@ -280,21 +295,27 @@ METHOD(listener_t, message, bool, private_tkm_listener_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain) { + tkm_keymat_t *keymat; + isa_id_type isa_id; + auth_payload_t *auth_payload; + if (!incoming || !plain || message->get_exchange_type(message) != IKE_AUTH) { return TRUE; } - tkm_keymat_t * const keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); - const isa_id_type isa_id = keymat->get_isa_id(keymat); + keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa); + isa_id = keymat->get_isa_id(keymat); DBG1(DBG_IKE, "saving AUTHENTICATION payload for authorize hook" - " (ISA context %llu)", isa_id); + " (ISA context %llu)", isa_id); - auth_payload_t * const auth_payload = - (auth_payload_t*)message->get_payload(message, AUTHENTICATION); + auth_payload = (auth_payload_t*)message->get_payload(message, + AUTHENTICATION); if (auth_payload) { - const chunk_t auth_data = auth_payload->get_data(auth_payload); + chunk_t auth_data; + + auth_data = auth_payload->get_data(auth_payload); keymat->set_auth_payload(keymat, &auth_data); } else diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c index 2723a3ee5..a07326798 100644 --- a/src/charon-tkm/src/tkm/tkm_nonceg.c +++ b/src/charon-tkm/src/tkm/tkm_nonceg.c @@ -43,6 +43,7 @@ METHOD(nonce_gen_t, get_nonce, bool, private_tkm_nonceg_t *this, size_t size, u_int8_t *buffer) { nonce_type nonce; + if (ike_nc_create(this->context_id, size, &nonce) != TKM_OK) { return FALSE; diff --git a/src/charon-tkm/src/tkm/tkm_private_key.c b/src/charon-tkm/src/tkm/tkm_private_key.c index 9e3f96c95..db57ec1c7 100644 --- a/src/charon-tkm/src/tkm/tkm_private_key.c +++ b/src/charon-tkm/src/tkm/tkm_private_key.c @@ -63,16 +63,18 @@ METHOD(private_key_t, sign, bool, { signature_type sig; init_message_type msg; + sign_info_t sign; + isa_id_type isa_id; if (data.ptr == NULL) { DBG1(DBG_LIB, "unable to get signature information"); return FALSE; } - sign_info_t sign = *(sign_info_t *)(data.ptr); + sign = *(sign_info_t *)(data.ptr); chunk_to_sequence(&sign.init_message, &msg, sizeof(init_message_type)); - const isa_id_type isa_id = sign.isa_id; + isa_id = sign.isa_id; chunk_free(&sign.init_message); if (ike_isa_sign(isa_id, 1, msg, &sig) != TKM_OK) @@ -141,6 +143,8 @@ METHOD(private_key_t, destroy, void, tkm_private_key_t *tkm_private_key_init(identification_t * const id) { private_tkm_private_key_t *this; + certificate_t *cert; + public_key_t *pubkey; INIT(this, .public = { @@ -164,7 +168,6 @@ tkm_private_key_t *tkm_private_key_init(identification_t * const id) ); /* get key type from associated public key */ - certificate_t *cert; cert = lib->credmgr->get_cert(lib->credmgr, CERT_ANY, KEY_ANY, id, FALSE); if (!cert) { @@ -172,7 +175,7 @@ tkm_private_key_t *tkm_private_key_init(identification_t * const id) return NULL; } - public_key_t *pubkey = cert->get_public_key(cert); + pubkey = cert->get_public_key(cert); if (!pubkey) { cert->destroy(cert); diff --git a/src/charon-tkm/src/tkm/tkm_utils.c b/src/charon-tkm/src/tkm/tkm_utils.c index e0c3e5752..e0692b893 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.c +++ b/src/charon-tkm/src/tkm/tkm_utils.c @@ -26,18 +26,19 @@ struct sequence_type { typedef struct sequence_type sequence_type; void sequence_to_chunk(const byte_t * const first, const uint32_t len, - chunk_t * const chunk) + chunk_t * const chunk) { *chunk = chunk_alloc(len); memcpy(chunk->ptr, first, len); } void chunk_to_sequence(const chunk_t * const chunk, void *sequence, - const uint32_t typelen) + const uint32_t typelen) { const uint32_t seqlenmax = typelen - sizeof(uint32_t); - memset(sequence, 0, typelen); sequence_type *seq = sequence; + + memset(sequence, 0, typelen); if (chunk->len > seqlenmax) { DBG1(DBG_LIB, "chunk too large to fit into sequence %d > %d, limiting" diff --git a/src/charon-tkm/src/tkm/tkm_utils.h b/src/charon-tkm/src/tkm/tkm_utils.h index ac8fac742..308c58fbb 100644 --- a/src/charon-tkm/src/tkm/tkm_utils.h +++ b/src/charon-tkm/src/tkm/tkm_utils.h @@ -33,7 +33,7 @@ * @param chunk pointer to chunk struct */ void sequence_to_chunk(const byte_t * const first, const uint32_t len, - chunk_t * const chunk); + chunk_t * const chunk); /** * Convert chunk to variable-length byte sequence. @@ -43,6 +43,6 @@ void sequence_to_chunk(const byte_t * const first, const uint32_t len, * @param typelen length of sequence type */ void chunk_to_sequence(const chunk_t * const chunk, void *sequence, - const uint32_t typelen); + const uint32_t typelen); #endif /** TKM_UTILS_H_ @}*/ -- cgit v1.2.3