Merge branch 'tkm'
This adds charon-tkm a special build of the charon IKEv2 daemon that delegates security critical operations to a separate process (TKM = Trusted Key Manager).
This commit is contained in:
commit
7f0f185bed
1
HACKING
1
HACKING
|
@ -18,6 +18,7 @@ the code, you need the following tools:
|
|||
- lex/flex
|
||||
- yacc/bison
|
||||
- gperf
|
||||
- check
|
||||
- optionally Doxygen
|
||||
|
||||
To check out the master branch, use:
|
||||
|
|
8
NEWS
8
NEWS
|
@ -43,6 +43,14 @@ strongswan-5.0.3
|
|||
any authentication. Therefore, to use this backend it has to be selected
|
||||
explicitly with rightauth2=xauth-noauth.
|
||||
|
||||
- The new charon-tkm IKEv2 daemon delegates security critical operations to a
|
||||
separate process. This has the benefit that the network facing daemon has no
|
||||
knowledge of keying material used to protect child SAs. Thus subverting
|
||||
charon-tkm does not result in the compromise of cryptographic keys.
|
||||
The extracted functionality has been implemented from scratch in a minimal TCB
|
||||
(trusted computing base) in the Ada programming language. Further information
|
||||
can be found at http://www.codelabs.ch/tkm/.
|
||||
|
||||
strongswan-5.0.2
|
||||
----------------
|
||||
|
||||
|
|
23
configure.in
23
configure.in
|
@ -236,6 +236,8 @@ ARG_ENABL_SET([radattr], [enable plugin to inject and process custom RADI
|
|||
ARG_ENABL_SET([vstr], [enforce using the Vstr string library to replace glibc-like printf hooks.])
|
||||
ARG_ENABL_SET([monolithic], [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.])
|
||||
ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.])
|
||||
ARG_ENABL_SET([unit-tests], [enable unit tests using the check test framework.])
|
||||
ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.])
|
||||
|
||||
# ===================================
|
||||
# option to disable default options
|
||||
|
@ -258,6 +260,8 @@ if test -z "$CFLAGS"; then
|
|||
CFLAGS="-g -O2 -Wall -Wno-format -Wno-pointer-sign"
|
||||
fi
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
AC_LIB_PREFIX
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
|
@ -894,6 +898,16 @@ AC_SUBST(dev_headers)
|
|||
|
||||
CFLAGS="$CFLAGS -include `pwd`/config.h"
|
||||
|
||||
if test x$tkm = xtrue; then
|
||||
AC_PATH_PROG([GPRBUILD], [gprbuild], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
|
||||
fi
|
||||
|
||||
if test x$unit_tests = xtrue; then
|
||||
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4])
|
||||
AC_SUBST(CHECK_CFLAGS)
|
||||
AC_SUBST(CHECK_LIBS)
|
||||
fi
|
||||
|
||||
# ===============================================
|
||||
# collect plugin list for strongSwan components
|
||||
# ===============================================
|
||||
|
@ -1190,9 +1204,9 @@ AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
|
|||
AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
|
||||
AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
|
||||
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
|
||||
|
@ -1208,6 +1222,8 @@ AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
|
|||
AM_CONDITIONAL(USE_PTS, test x$pts = xtrue)
|
||||
AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers)
|
||||
AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
|
||||
AM_CONDITIONAL(UNITTESTS, test x$unit_tests = xtrue)
|
||||
AM_CONDITIONAL(USE_TKM, test x$tkm = xtrue)
|
||||
|
||||
# ========================
|
||||
# set global definitions
|
||||
|
@ -1309,6 +1325,7 @@ AC_CONFIG_FILES([
|
|||
src/libimcv/plugins/imv_os/Makefile
|
||||
src/charon/Makefile
|
||||
src/charon-nm/Makefile
|
||||
src/charon-tkm/Makefile
|
||||
src/libcharon/Makefile
|
||||
src/libcharon/plugins/eap_aka/Makefile
|
||||
src/libcharon/plugins/eap_aka_3gpp2/Makefile
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
obj
|
|
@ -0,0 +1,54 @@
|
|||
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 = \
|
||||
-XOBJ_DIR=$(CURDIR)/obj \
|
||||
-cargs $(INCLUDES) $(DEFS) \
|
||||
-largs $(LIBLD) $(LIBFL)
|
||||
|
||||
# plugins to enable
|
||||
PLUGINS = \
|
||||
kernel-netlink \
|
||||
pem \
|
||||
socket-default \
|
||||
openssl \
|
||||
stroke
|
||||
|
||||
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
|
|
@ -0,0 +1,20 @@
|
|||
with "build_common";
|
||||
|
||||
project Build_Charon is
|
||||
|
||||
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;
|
||||
|
||||
package Binder is
|
||||
for Default_Switches ("ada") use Build_Common.Ada_Binder_Switches;
|
||||
end Binder;
|
||||
|
||||
end Build_Charon;
|
|
@ -0,0 +1,25 @@
|
|||
with "tkmrpc_client";
|
||||
with "tkmrpc_server-ees";
|
||||
|
||||
project Build_Common is
|
||||
|
||||
for Source_Dirs use ();
|
||||
|
||||
Obj_Dir := "obj";
|
||||
|
||||
C_Compiler_Switches := ("-W",
|
||||
"-Wall",
|
||||
"-Wno-unused-parameter");
|
||||
Ada_Compiler_Switches := ("-gnatwale",
|
||||
"-gnatygAdISuxo",
|
||||
"-gnata",
|
||||
"-gnatVa",
|
||||
"-gnat05",
|
||||
"-gnatf",
|
||||
"-fstack-check",
|
||||
"-gnato",
|
||||
"-g");
|
||||
|
||||
Ada_Binder_Switches := ("-E");
|
||||
|
||||
end Build_Common;
|
|
@ -0,0 +1,14 @@
|
|||
with "build_common";
|
||||
|
||||
project Build_Tests is
|
||||
|
||||
for Languages use ("Ada", "C");
|
||||
for Source_Dirs use ("src/ees", "src/ehandler", "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.C_Compiler_Switches;
|
||||
end Compiler;
|
||||
|
||||
end Build_Tests;
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <hydra.h>
|
||||
#include <daemon.h>
|
||||
#include <library.h>
|
||||
#include <utils/backtrace.h>
|
||||
#include <threading/thread.h>
|
||||
#include <sa/keymat.h>
|
||||
#include <credentials/credential_manager.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_nonceg.h"
|
||||
#include "tkm_diffie_hellman.h"
|
||||
#include "tkm_keymat.h"
|
||||
#include "tkm_listener.h"
|
||||
#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.
|
||||
*/
|
||||
static tkm_listener_t *listener;
|
||||
|
||||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
/* TKM credential set */
|
||||
tkm_cred_t *creds;
|
||||
|
||||
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")");
|
||||
|
||||
/* 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_2048_BIT),
|
||||
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"),
|
||||
};
|
||||
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))
|
||||
{
|
||||
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 */
|
||||
if (!tkm_init())
|
||||
{
|
||||
DBG1(DBG_DMN, "init of TKM client failed - aborting %s", dmn_name);
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
/* register TKM authorization hook */
|
||||
listener = tkm_listener_create();
|
||||
charon->bus->add_listener(charon->bus, &listener->listener);
|
||||
|
||||
/* register TKM credential set */
|
||||
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;
|
||||
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;
|
||||
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();
|
||||
libhydra_deinit();
|
||||
library_deinit();
|
||||
tkm_deinit();
|
||||
return status;
|
||||
}
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <hydra.h>
|
||||
#include <utils/debug.h>
|
||||
#include <tkm/constants.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful, but
|
||||
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
-- for more details.
|
||||
--
|
||||
|
||||
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 (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);
|
||||
end Init;
|
||||
|
||||
end Esa_Event_Service;
|
|
@ -0,0 +1,30 @@
|
|||
--
|
||||
-- Copyright (C) 2012 Reto Buerki
|
||||
-- Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
-- Hochschule fuer Technik Rapperswil
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it
|
||||
-- under the terms of the GNU General Public License as published by the
|
||||
-- Free Software Foundation; either version 2 of the License, or (at your
|
||||
-- option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful, but
|
||||
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
-- for more details.
|
||||
--
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
|
||||
package Esa_Event_Service
|
||||
is
|
||||
|
||||
procedure Init (Address : Interfaces.C.Strings.chars_ptr);
|
||||
pragma Export (C, Init, "ees_server_init");
|
||||
-- Initialize Esa Event Service (EES) with given address.
|
||||
|
||||
procedure Finalize;
|
||||
pragma Export (C, Finalize, "ees_server_finalize");
|
||||
-- Finalize EES.
|
||||
|
||||
end Esa_Event_Service;
|
|
@ -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;
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include "eh_callbacks.h"
|
||||
|
||||
void charon_terminate(char *msg)
|
||||
{
|
||||
DBG1(DBG_DMN, "critical TKM error, terminating!");
|
||||
DBG1(DBG_DMN, msg);
|
||||
kill(0, SIGTERM);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_
|
||||
|
||||
/**
|
||||
* Log given message and terminate charon.
|
||||
*/
|
||||
void charon_terminate(char *msg);
|
||||
|
||||
#endif /** EH_CALLBACKS_H_ @}*/
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful, but
|
||||
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
-- for more details.
|
||||
--
|
||||
|
||||
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;
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful, but
|
||||
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
-- for more details.
|
||||
--
|
||||
|
||||
package Exception_Handler
|
||||
is
|
||||
|
||||
procedure Init;
|
||||
pragma Export (C, Init, "ehandler_init");
|
||||
-- Register last-chance exception handler.
|
||||
|
||||
end Exception_Handler;
|
|
@ -0,0 +1 @@
|
|||
obj
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
#include <tkm/client.h>
|
||||
#include <tkm/constants.h>
|
||||
|
||||
#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);
|
||||
extern void ehandler_init(void);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
active_requests_type max_requests;
|
||||
char *ikesock, *eessock;
|
||||
tkm_limits_t limits;
|
||||
|
||||
/* initialize TKM client library */
|
||||
tkmlib_init();
|
||||
ehandler_init();
|
||||
|
||||
ikesock = lib->settings->get_str(lib->settings, "%s.ike_socket", IKE_SOCKET,
|
||||
charon->name);
|
||||
if (ike_init(ikesock) != TKM_OK)
|
||||
{
|
||||
tkmlib_final();
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_DMN, "connected to TKM via socket '%s'", ikesock);
|
||||
|
||||
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)
|
||||
{
|
||||
ees_server_finalize();
|
||||
tkmlib_final();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get limits from tkm */
|
||||
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;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.idmgr = tkm_id_manager_create(limits),
|
||||
.chunk_map = tkm_chunk_map_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);
|
||||
this->public.chunk_map->destroy(this->public.chunk_map);
|
||||
|
||||
ees_server_finalize();
|
||||
|
||||
tkmlib_final();
|
||||
free(this);
|
||||
tkm = NULL;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_
|
||||
|
||||
#include "tkm_id_manager.h"
|
||||
#include "tkm_chunk_map.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;
|
||||
|
||||
/**
|
||||
* Chunk-to-ID mappings.
|
||||
*/
|
||||
tkm_chunk_map_t *chunk_map;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <collections/hashtable.h>
|
||||
#include <threading/rwlock.h>
|
||||
#include <utils/chunk.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#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;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
entry_t *entry;
|
||||
INIT(entry,
|
||||
.key = chunk_clone(*data),
|
||||
.value = id
|
||||
);
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
entry = this->mappings->put(this->mappings, (void*)&entry->key, entry);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(tkm_chunk_map_t, get_id, uint64_t,
|
||||
private_tkm_chunk_map_t * const this, chunk_t *data)
|
||||
{
|
||||
entry_t *entry;
|
||||
this->lock->read_lock(this->lock);
|
||||
entry = this->mappings->get(this->mappings, data);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
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);
|
||||
entry = this->mappings->remove(this->mappings, data);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
entry_destroy(entry);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(tkm_chunk_map_t, destroy, void,
|
||||
private_tkm_chunk_map_t *this)
|
||||
{
|
||||
entry_t *entry;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
enumerator = this->mappings->create_enumerator(this->mappings);
|
||||
while (enumerator->enumerate(enumerator, NULL, &entry))
|
||||
{
|
||||
entry_destroy(entry);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
this->mappings->destroy(this->mappings);
|
||||
this->lock->destroy(this->lock);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-chunk-map chunk map
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_CHUNK_MAP_H_
|
||||
#define TKM_CHUNK_MAP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utils/chunk.h>
|
||||
|
||||
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_ @}*/
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <credentials/sets/mem_cred.h>
|
||||
#include <collections/hashtable.h>
|
||||
#include <threading/rwlock.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
identification_t *entry;
|
||||
|
||||
if (!id)
|
||||
{
|
||||
return this->known_keys->create_enumerator(this->known_keys);
|
||||
}
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
entry = this->known_keys->get(this->known_keys, id);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
identification_t *clone = id->clone(id);
|
||||
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);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-credential credential set
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_CRED_H_
|
||||
#define TKM_CRED_H_
|
||||
|
||||
typedef struct tkm_cred_t tkm_cred_t;
|
||||
|
||||
#include <credentials/credential_set.h>
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyrigth (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <tkm/client.h>
|
||||
#include <tkm/constants.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_utils.h"
|
||||
#include "tkm_diffie_hellman.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Context id.
|
||||
*/
|
||||
dh_id_type context_id;
|
||||
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, void,
|
||||
private_tkm_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
sequence_to_chunk(this->pubvalue.data, this->pubvalue.size, value);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, status_t,
|
||||
private_tkm_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_empty;
|
||||
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(this->context_id, 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)
|
||||
{
|
||||
if (ike_dh_reset(this->context_id) != TKM_OK)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
METHOD(tkm_diffie_hellman_t, get_id, dh_id_type,
|
||||
private_tkm_diffie_hellman_t *this)
|
||||
{
|
||||
return this->context_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
},
|
||||
.get_id = _get_id,
|
||||
},
|
||||
.group = group,
|
||||
.context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_DH),
|
||||
);
|
||||
|
||||
if (!this->context_id)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ike_dh_create(this->context_id, group, &this->pubvalue) != TKM_OK)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-dh diffie hellman
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_DIFFIE_HELLMAN_H_
|
||||
#define TKM_DIFFIE_HELLMAN_H_
|
||||
|
||||
typedef struct tkm_diffie_hellman_t tkm_diffie_hellman_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
/**
|
||||
* diffie_hellman_t implementation using the trusted key manager.
|
||||
*/
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/oid.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-credential-enc credential encoder
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_ENCODER_H_
|
||||
#define TKM_ENCODER_H_
|
||||
|
||||
#include <credentials/cred_encoding.h>
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "tkm_id_manager.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <threading/rwlock.h>
|
||||
|
||||
#define TKM_LIMIT 100
|
||||
|
||||
ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ESA,
|
||||
"NONCE_CONTEXT",
|
||||
"DH_CONTEXT",
|
||||
"CC_CONTEXT"
|
||||
"ISA_CONTEXT",
|
||||
"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;
|
||||
|
||||
/**
|
||||
* private data of tkm_id_manager
|
||||
*/
|
||||
struct private_tkm_id_manager_t {
|
||||
|
||||
/**
|
||||
* public functions
|
||||
*/
|
||||
tkm_id_manager_t public;
|
||||
|
||||
/**
|
||||
* Per-kind array of free context ids
|
||||
*/
|
||||
bool* ctxids[TKM_CTX_MAX];
|
||||
|
||||
/**
|
||||
* Per-kind context limits.
|
||||
*/
|
||||
tkm_limits_t limits;
|
||||
|
||||
/**
|
||||
* 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 id = 0;
|
||||
uint64_t j;
|
||||
|
||||
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]);
|
||||
for (j = 0; j < this->limits[kind]; j++)
|
||||
{
|
||||
if (!this->ctxids[kind][j])
|
||||
{
|
||||
this->ctxids[kind][j] = true;
|
||||
id = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
const int idx = id - 1;
|
||||
|
||||
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]);
|
||||
this->ctxids[kind][idx] = false;
|
||||
this->locks[kind]->unlock(this->locks[kind]);
|
||||
|
||||
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++)
|
||||
{
|
||||
free(this->ctxids[i]);
|
||||
this->locks[i]->destroy(this->locks[i]);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits)
|
||||
{
|
||||
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->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]);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-id-manager id manager
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_ID_MANAGER_H_
|
||||
#define TKM_ID_MANAGER_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct tkm_id_manager_t tkm_id_manager_t;
|
||||
typedef enum tkm_context_kind_t tkm_context_kind_t;
|
||||
|
||||
/**
|
||||
* Trusted key manager context kinds.
|
||||
*/
|
||||
enum tkm_context_kind_t {
|
||||
/** Nonce context */
|
||||
TKM_CTX_NONCE,
|
||||
/** Diffie-Hellman context */
|
||||
TKM_CTX_DH,
|
||||
/** Certificate chain context */
|
||||
TKM_CTX_CC,
|
||||
/** IKE SA context */
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for 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).
|
||||
*/
|
||||
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 using the given context limits.
|
||||
*/
|
||||
tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits);
|
||||
|
||||
#endif /** TKM_ID_MANAGER_H_ @}*/
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <linux/xfrm.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/chunk.h>
|
||||
#include <tkm/constants.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_utils.h"
|
||||
#include "tkm_types.h"
|
||||
#include "tkm_keymat.h"
|
||||
#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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* RNG used for SPI generation.
|
||||
*/
|
||||
rng_t *rng;
|
||||
|
||||
/**
|
||||
* CHILD/ESP SA database.
|
||||
*/
|
||||
tkm_kernel_sad_t *sad;
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
if (!this->rng)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to create RNG");
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid);
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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 = *(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;
|
||||
}
|
||||
|
||||
/* Initiator if encr_r is passed as enc_key to the inbound add_sa call */
|
||||
initiator = esa.is_encr_r && inbound;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
goto sad_failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
!= 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)
|
||||
{
|
||||
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)
|
||||
!= 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
|
||||
goto failure;
|
||||
}
|
||||
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");
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
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 SUCCESS;
|
||||
}
|
||||
|
||||
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 SUCCESS;
|
||||
}
|
||||
|
||||
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 SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, flush_policies, status_t,
|
||||
private_tkm_kernel_ipsec_t *this)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
METHOD(kernel_ipsec_t, bypass_socket, bool,
|
||||
private_tkm_kernel_ipsec_t *this, int fd, int 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)
|
||||
{
|
||||
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,
|
||||
private_tkm_kernel_ipsec_t *this)
|
||||
{
|
||||
DESTROY_IF(this->rng);
|
||||
DESTROY_IF(this->sad);
|
||||
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,
|
||||
},
|
||||
},
|
||||
.sad = tkm_kernel_sad_create(),
|
||||
);
|
||||
|
||||
if (!this->sad)
|
||||
{
|
||||
DBG1(DBG_KNL, "unable to create SAD");
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-kernel-ipsec kernel ipsec
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_KERNEL_IPSEC_H_
|
||||
#define TKM_KERNEL_IPSEC_H_
|
||||
|
||||
#include <kernel/kernel_ipsec.h>
|
||||
|
||||
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_ @}*/
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <threading/mutex.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
status_t result;
|
||||
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);
|
||||
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;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-kernel-sad kernel sad
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_KERNEL_SAD_H_
|
||||
#define TKM_KERNEL_SAD_H_
|
||||
|
||||
#include <networking/host.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
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_ @}*/
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Copyrigth (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <daemon.h>
|
||||
#include <tkm/constants.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_types.h"
|
||||
#include "tkm_utils.h"
|
||||
#include "tkm_diffie_hellman.h"
|
||||
#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;
|
||||
|
||||
/**
|
||||
* IKE_SA Role, initiator or responder.
|
||||
*/
|
||||
bool initiator;
|
||||
|
||||
/**
|
||||
* Inbound AEAD.
|
||||
*/
|
||||
aead_t *aead_in;
|
||||
|
||||
/**
|
||||
* Outbound AEAD.
|
||||
*/
|
||||
aead_t *aead_out;
|
||||
|
||||
/**
|
||||
* ISA context id.
|
||||
*/
|
||||
isa_id_type isa_ctx_id;
|
||||
|
||||
/**
|
||||
* AE context id.
|
||||
*/
|
||||
ae_id_type ae_ctx_id;
|
||||
|
||||
/**
|
||||
* AUTH payload chunk.
|
||||
*/
|
||||
chunk_t auth_payload;
|
||||
|
||||
/**
|
||||
* Peer init message chunk.
|
||||
*/
|
||||
chunk_t other_init_msg;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 *signer_i, *signer_r;
|
||||
crypter_t *crypter_i, *crypter_r;
|
||||
|
||||
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!",
|
||||
transform_type_names, INTEGRITY_ALGORITHM,
|
||||
integrity_algorithm_names, int_alg);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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(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)
|
||||
{
|
||||
u_int16_t enc_alg, int_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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
/* Acquire nonce context id */
|
||||
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");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get DH context id */
|
||||
tkm_dh = (tkm_diffie_hellman_t *)dh;
|
||||
dh_id = tkm_dh->get_id(tkm_dh);
|
||||
|
||||
if (this->initiator)
|
||||
{
|
||||
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, sizeof(nonce_type));
|
||||
spi_loc = id->get_responder_spi(id);
|
||||
spi_rem = id->get_initiator_spi(id);
|
||||
}
|
||||
|
||||
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,
|
||||
nonce_rem, this->initiator, spi_loc, spi_rem,
|
||||
&sk_ai, &sk_ar, &sk_ei, &sk_er);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (res != TKM_OK)
|
||||
{
|
||||
DBG1(DBG_IKE, "key derivation failed (isa: %llu)", this->isa_ctx_id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
chunk_clear(&c_ai);
|
||||
chunk_clear(&c_ar);
|
||||
chunk_clear(&c_ei);
|
||||
chunk_clear(&c_er);
|
||||
|
||||
if (!this->aead_in || !this->aead_out)
|
||||
{
|
||||
DBG1(DBG_IKE, "could not initialize AEAD transforms");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* TODO: Add failure handler (see keymat_v2.c) */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
METHOD(keymat_t, get_aead, aead_t*,
|
||||
private_tkm_keymat_t *this, bool in)
|
||||
{
|
||||
return in ? this->aead_in : this->aead_out;
|
||||
}
|
||||
|
||||
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 */
|
||||
this->other_init_msg = chunk_clone(ike_sa_init);
|
||||
*octets = chunk_empty;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
METHOD(keymat_v2_t, get_skd, pseudo_random_function_t,
|
||||
private_tkm_keymat_t *this, chunk_t *skd)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
/* 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);
|
||||
chunk_free(&this->auth_payload);
|
||||
chunk_free(&this->other_init_msg);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(tkm_keymat_t, get_isa_id, isa_id_type,
|
||||
private_tkm_keymat_t *this)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
METHOD(tkm_keymat_t, get_peer_init_msg, chunk_t*,
|
||||
private_tkm_keymat_t *this)
|
||||
{
|
||||
return &this->other_init_msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
tkm_keymat_t *tkm_keymat_create(bool initiator)
|
||||
{
|
||||
private_tkm_keymat_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.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,
|
||||
},
|
||||
.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)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-keymat keymat
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_KEYMAT_H_
|
||||
#define TKM_KEYMAT_H_
|
||||
|
||||
#include <sa/ikev2/keymat_v2.h>
|
||||
|
||||
typedef struct tkm_keymat_t tkm_keymat_t;
|
||||
|
||||
/**
|
||||
* Derivation and management of sensitive keying material, TKM variant.
|
||||
*/
|
||||
struct tkm_keymat_t {
|
||||
|
||||
/**
|
||||
* Implements keymat_v2_t.
|
||||
*/
|
||||
keymat_v2_t keymat_v2;
|
||||
|
||||
/**
|
||||
* Get ISA context id.
|
||||
*
|
||||
* @return id of associated ISA context.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_ @}*/
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* Copyrigth (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <daemon.h>
|
||||
#include <encoding/payloads/auth_payload.h>
|
||||
#include <utils/chunk.h>
|
||||
#include <tkm/types.h>
|
||||
#include <tkm/constants.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_listener.h"
|
||||
#include "tkm_keymat.h"
|
||||
#include "tkm_utils.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;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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");
|
||||
rounds->destroy(rounds);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DBG1(DBG_IKE, "error setting user certificate of cert chain"
|
||||
" (cc_id: %llu)", cc_id);
|
||||
rounds->destroy(rounds);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* process intermediate CA certificates */
|
||||
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");
|
||||
rounds->destroy(rounds);
|
||||
enumerator->destroy(enumerator);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
rounds->destroy(rounds);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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, 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 *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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
if (!build_cert_chain(ike_sa, cc_id))
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to build certificate chain");
|
||||
*success = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
auth = keymat->get_auth_payload(keymat);
|
||||
if (!auth->ptr)
|
||||
{
|
||||
DBG1(DBG_IKE, "no AUTHENTICATION data available");
|
||||
*success = FALSE;
|
||||
}
|
||||
|
||||
other_init_msg = keymat->get_peer_init_msg(keymat);
|
||||
if (!other_init_msg->ptr)
|
||||
{
|
||||
DBG1(DBG_IKE, "no peer init message available");
|
||||
*success = FALSE;
|
||||
}
|
||||
|
||||
chunk_to_sequence(auth, &signature, sizeof(signature_type));
|
||||
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);
|
||||
*success = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
auth_payload = (auth_payload_t*)message->get_payload(message,
|
||||
AUTHENTICATION);
|
||||
if (auth_payload)
|
||||
{
|
||||
chunk_t auth_data;
|
||||
|
||||
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)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
tkm_listener_t *tkm_listener_create()
|
||||
{
|
||||
private_tkm_listener_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.listener = {
|
||||
.authorize = _authorize,
|
||||
.message = _message,
|
||||
.alert = _alert,
|
||||
},
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-listener listener
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_LISTENER_H_
|
||||
#define TKM_LISTENER_H_
|
||||
|
||||
#include <bus/listeners/listener.h>
|
||||
|
||||
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_ @}*/
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyrigth (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <tkm/client.h>
|
||||
#include <tkm/constants.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (ike_nc_create(this->context_id, size, &nonce) != TKM_OK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(buffer, &nonce.data, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(nonce_gen_t, allocate_nonce, bool,
|
||||
private_tkm_nonceg_t *this, size_t size, chunk_t *chunk)
|
||||
{
|
||||
*chunk = chunk_alloc(size);
|
||||
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,
|
||||
private_tkm_nonceg_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(tkm_nonceg_t, get_id, nc_id_type,
|
||||
private_tkm_nonceg_t *this)
|
||||
{
|
||||
return this->context_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
},
|
||||
.get_id = _get_id,
|
||||
},
|
||||
.context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_NONCE),
|
||||
);
|
||||
|
||||
if (!this->context_id)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-nonceg nonce generator
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_NONCEG_H_
|
||||
#define TKM_NONCEG_H_
|
||||
|
||||
typedef struct tkm_nonceg_t tkm_nonceg_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
/**
|
||||
* nonce_gen_t implementation using the trusted key manager.
|
||||
*/
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a tkm_nonceg_t instance.
|
||||
*
|
||||
* @return created tkm_nonceg_t
|
||||
*/
|
||||
tkm_nonceg_t *tkm_nonceg_create();
|
||||
|
||||
#endif /** TKM_NONCEG_H_ @}*/
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <tkm/constants.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#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 ID.
|
||||
*/
|
||||
identification_t *id;
|
||||
|
||||
/**
|
||||
* Key type.
|
||||
*/
|
||||
key_type_t key_type;
|
||||
|
||||
/**
|
||||
* Reference count.
|
||||
*/
|
||||
refcount_t ref;
|
||||
|
||||
};
|
||||
|
||||
METHOD(private_key_t, get_type, key_type_t,
|
||||
private_tkm_private_key_t *this)
|
||||
{
|
||||
return this->key_type;
|
||||
}
|
||||
|
||||
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;
|
||||
sign_info_t sign;
|
||||
isa_id_type isa_id;
|
||||
|
||||
if (data.ptr == NULL)
|
||||
{
|
||||
DBG1(DBG_LIB, "unable to get signature information");
|
||||
return FALSE;
|
||||
}
|
||||
sign = *(sign_info_t *)(data.ptr);
|
||||
|
||||
chunk_to_sequence(&sign.init_message, &msg, sizeof(init_message_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->id->get_encoding(this->id);
|
||||
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))
|
||||
{
|
||||
this->id->destroy(this->id);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
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 = {
|
||||
.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,
|
||||
.id = id->clone(id),
|
||||
);
|
||||
|
||||
/* get key type from associated public key */
|
||||
cert = lib->credmgr->get_cert(lib->credmgr, CERT_ANY, KEY_ANY, id, FALSE);
|
||||
if (!cert)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-privkey private key
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_PRIVATE_KEY_H_
|
||||
#define TKM_PRIVATE_KEY_H_
|
||||
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
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 with given key ID.
|
||||
*/
|
||||
tkm_private_key_t *tkm_private_key_init(identification_t * const id);
|
||||
|
||||
#endif /** TKM_PRIVATE_KEY_H_ @}*/
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#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;
|
||||
|
||||
/**
|
||||
* ASN.1 blob of pubkey.
|
||||
*/
|
||||
chunk_t asn_blob;
|
||||
|
||||
/**
|
||||
* Key type.
|
||||
*/
|
||||
key_type_t key_type;
|
||||
|
||||
/**
|
||||
* Reference count.
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(public_key_t, get_type, key_type_t,
|
||||
private_tkm_public_key_t *this)
|
||||
{
|
||||
return this->key_type;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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*,
|
||||
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->asn_blob);
|
||||
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 blob = chunk_empty;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!blob.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,
|
||||
.asn_blob = chunk_clone(blob),
|
||||
.key_type = type,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-pubkey public key
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_PUBLIC_KEY_H_
|
||||
#define TKM_PUBLIC_KEY_H_
|
||||
|
||||
#include <credentials/keys/public_key.h>
|
||||
|
||||
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.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @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_ @}*/
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-types types
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_TYPES_H_
|
||||
#define TKM_TYPES_H_
|
||||
|
||||
#include <tkm/types.h>
|
||||
#include <utils/chunk.h>
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
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_ @}*/
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#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,
|
||||
const uint32_t typelen)
|
||||
{
|
||||
const uint32_t seqlenmax = typelen - sizeof(uint32_t);
|
||||
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"
|
||||
" to %d bytes", chunk->len, seqlenmax, seqlenmax);
|
||||
seq->size = seqlenmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq->size = chunk->len;
|
||||
}
|
||||
memcpy(seq->data, chunk->ptr, seq->size);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tkm-utils utils
|
||||
* @{ @ingroup tkm
|
||||
*/
|
||||
|
||||
#ifndef TKM_UTILS_H_
|
||||
#define TKM_UTILS_H_
|
||||
|
||||
#include <utils/chunk.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Convert chunk to variable-length byte sequence.
|
||||
*
|
||||
* @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,
|
||||
const uint32_t typelen);
|
||||
|
||||
#endif /** TKM_UTILS_H_ @}*/
|
|
@ -0,0 +1 @@
|
|||
test_runner
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "tkm_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;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "tkm_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");
|
||||
fail_if(!dh->get_id(dh), "Invalid context id (0)");
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "tkm_id_manager.h"
|
||||
|
||||
static const tkm_limits_t limits = {125, 100, 55, 30, 200, 42};
|
||||
|
||||
START_TEST(test_id_mgr_creation)
|
||||
{
|
||||
tkm_id_manager_t *idmgr = NULL;
|
||||
|
||||
idmgr = tkm_id_manager_create(limits);
|
||||
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(limits);
|
||||
|
||||
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(limits);
|
||||
|
||||
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_acquire_id_same)
|
||||
{
|
||||
int id1 = 0, id2 = 0;
|
||||
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");
|
||||
|
||||
/* 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;
|
||||
bool released = false;
|
||||
tkm_id_manager_t *idmgr = tkm_id_manager_create(limits);
|
||||
|
||||
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(limits);
|
||||
|
||||
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(limits);
|
||||
|
||||
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_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);
|
||||
|
||||
return tc;
|
||||
}
|
|
@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "tkm_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;
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <daemon.h>
|
||||
#include <hydra.h>
|
||||
#include <config/proposal.h>
|
||||
#include <encoding/payloads/ike_header.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_nonceg.h"
|
||||
#include "tkm_diffie_hellman.h"
|
||||
#include "tkm_keymat.h"
|
||||
#include "tkm_types.h"
|
||||
|
||||
START_TEST(test_derive_ike_keys)
|
||||
{
|
||||
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");
|
||||
fail_if(!keymat->get_isa_id(keymat), "Invalid ISA context id (0)");
|
||||
|
||||
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->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_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",
|
||||
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_v2.keymat.destroy(&keymat->keymat_v2.keymat);
|
||||
chunk_free(&pubvalue);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_derive_child_keys)
|
||||
{
|
||||
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->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;
|
||||
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_v2.keymat.destroy(&keymat->keymat_v2.keymat);
|
||||
chunk_free(&encr_i);
|
||||
chunk_free(&encr_r);
|
||||
}
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <tkm/client.h>
|
||||
|
||||
#include "tkm.h"
|
||||
#include "tkm_nonceg.h"
|
||||
|
||||
START_TEST(test_nonceg_creation)
|
||||
{
|
||||
tkm_nonceg_t *ng = NULL;
|
||||
|
||||
ng = tkm_nonceg_create();
|
||||
fail_if(ng == NULL, "Error creating tkm nonce generator");
|
||||
fail_if(ng->get_id(ng) == 0, "Invalid context id (0)");
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <library.h>
|
||||
#include <hydra.h>
|
||||
#include <daemon.h>
|
||||
|
||||
#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"),
|
||||
};
|
||||
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");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
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_utility_tests());
|
||||
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);
|
||||
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef TEST_RUNNER_H_
|
||||
#define TEST_RUNNER_H_
|
||||
|
||||
#include <check.h>
|
||||
|
||||
TCase *make_id_manager_tests(void);
|
||||
TCase *make_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);
|
||||
TCase *make_kernel_sad_tests(void);
|
||||
|
||||
#endif /** TEST_RUNNER_H_ */
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Reto Buerki
|
||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <tkm/types.h>
|
||||
|
||||
#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
|
||||
|
||||
START_TEST(test_chunk_to_sequence)
|
||||
{
|
||||
chunk_t chunk = chunk_from_thing("ABCDEFGH");
|
||||
key_type key;
|
||||
|
||||
chunk_to_sequence(&chunk, &key, sizeof(key_type));
|
||||
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;
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -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 <sec>]\n"
|
||||
" [--debug|--debug-more|--debug-all|--nolog]\n"
|
||||
" [--attach-gdb]\n");
|
||||
" [--attach-gdb] [--daemon <name>]\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 */
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/usr/local/lib/ipsec
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Wait until a given file appears
|
||||
#
|
||||
# Params:
|
||||
# $1 - filename
|
||||
# $2 - maximum time to wait in seconds, default is 5 seconds
|
||||
|
||||
if [[ $# -lt 1 || $# -gt 2 ]]
|
||||
then
|
||||
echo "invalid arguments"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
secs=$2
|
||||
[ ! $secs ] && secs=5
|
||||
|
||||
let steps=$secs*10
|
||||
for i in `seq 1 $steps`
|
||||
do
|
||||
# -f does not work for special files (e.g. UNIX domain sockets), use ls
|
||||
# instead
|
||||
ls $1 >/dev/null 2>&1
|
||||
[ $? -eq 0 ] && exit 0
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo "File '$1' not available after $secs second(s)"
|
||||
exit 1
|
|
@ -16,6 +16,8 @@ INC=$INC,libxml2-dev,libtspi-dev,libsqlite3-dev,openssh-server,tcpdump,psmisc
|
|||
INC=$INC,openssl,vim,sqlite3,conntrack,gdb,cmake,libxerces-c2-dev,libltdl-dev
|
||||
INC=$INC,liblog4cxx10-dev,libboost-thread-dev,libboost-system-dev,git-core
|
||||
INC=$INC,less,acpid,acpi-support-base,libldns-dev,libunbound-dev,dnsutils,screen
|
||||
INC=$INC,gnat,gprbuild,libahven3-dev,libxmlada4.1-dev,libgmpada3-dev
|
||||
INC=$INC,libalog0.4.1-base-dev
|
||||
SERVICES="apache2 dbus isc-dhcp-server slapd bind9"
|
||||
INC=$INC,${SERVICES// /,}
|
||||
EXC=iptables
|
||||
|
|
|
@ -46,6 +46,8 @@ do
|
|||
execute "mount $NBDPARTITION $LOOPDIR" 0
|
||||
execute "cp -rf $HOSTSDIR/${host}/etc $LOOPDIR" 0
|
||||
execute "cp -rf $HOSTSDIR/default/* $LOOPDIR" 0
|
||||
execute_chroot "ldconfig" 0
|
||||
|
||||
if [ "$host" = "winnetou" ]
|
||||
then
|
||||
execute "mkdir $LOOPDIR/var/log/apache2/ocsp" 0
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = anet
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.2.2
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make tests && make LIBRARY_KIND=static
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make LIBRARY_KIND=static install
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = tkm-rpc
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.1
|
||||
|
||||
export ADA_PROJECT_PATH=/root/libraries/lib/gnat
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make tests && make
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make install
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = x509-ada
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.1
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make tests && make
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make install
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = xfrm-ada
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.1
|
||||
|
||||
export ADA_PROJECT_PATH=/root/libraries/lib/gnat
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make install
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = tkm
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.1
|
||||
|
||||
export ADA_PROJECT_PATH=/root/libraries/lib/gnat
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make tests && make
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make install
|
|
@ -69,7 +69,10 @@ CONFIG_OPTS = \
|
|||
--enable-pkcs8 \
|
||||
--enable-unity \
|
||||
--enable-unbound \
|
||||
--enable-ipseckey
|
||||
--enable-ipseckey \
|
||||
--enable-tkm
|
||||
|
||||
export ADA_PROJECT_PATH=/root/libraries/lib/gnat
|
||||
|
||||
all: install
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = xfrm-proxy
|
||||
SRC = http://git.codelabs.ch/git/$(PKG).git
|
||||
REV = v0.1
|
||||
|
||||
export ADA_PROJECT_PATH=/root/libraries/lib/gnat
|
||||
|
||||
all: install
|
||||
|
||||
.$(PKG)-cloned:
|
||||
git clone $(SRC) $(PKG)
|
||||
cd $(PKG) && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built: .$(PKG)-cloned
|
||||
cd $(PKG) && make
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built
|
||||
cd $(PKG) && make install
|
|
@ -0,0 +1,3 @@
|
|||
A connection between the hosts <b>moon</b> and <b>sun</b> is set up. The host
|
||||
<b>moon</b> uses the Trusted Key Manager (TKM) and is the initiator of the
|
||||
transport connection. The authentication is based on X.509 certificates.
|
|
@ -0,0 +1,12 @@
|
|||
moon::ipsec stroke status 2> /dev/null::conn1.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
||||
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=1::YES
|
||||
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
||||
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
||||
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
||||
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
||||
moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
<tkmconfig>
|
||||
<local_identity id="1">
|
||||
<identity>moon.strongswan.org</identity>
|
||||
<certificate>moonCert.pem</certificate>
|
||||
</local_identity>
|
||||
<policy id="1">
|
||||
<mode>transport</mode>
|
||||
<local>
|
||||
<identity_id>1</identity_id>
|
||||
<ip>192.168.0.1</ip>
|
||||
</local>
|
||||
<remote>
|
||||
<identity>sun.strongswan.org</identity>
|
||||
<ip>192.168.0.2</ip>
|
||||
</remote>
|
||||
<lifetime>
|
||||
<soft>30</soft>
|
||||
<hard>60</hard>
|
||||
</lifetime>
|
||||
</policy>
|
||||
</tkmconfig>
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev2
|
||||
|
||||
conn host-host
|
||||
left=PH_IP_SUN
|
||||
leftcert=sunCert.pem
|
||||
leftid=sun.strongswan.org
|
||||
right=PH_IP_MOON
|
||||
rightid=moon.strongswan.org
|
||||
ike=aes256-sha512-modp4096!
|
||||
esp=aes256-sha512-modp4096!
|
||||
auto=add
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
moon::DAEMON_NAME=charon-tkm ipsec stop
|
||||
moon::killall tkm_keymanager
|
||||
moon::rm -f /tmp/tkm.rpc.ike /tmp/tkm.rpc.ees /tmp/tkm.log
|
||||
sun::ipsec stop
|
|
@ -0,0 +1,10 @@
|
|||
moon::rm /etc/ipsec.secrets
|
||||
moon::tkm_cfgtool -c /etc/tkm/tkm.conf -i /etc/ipsec.conf -t /etc/tkm/tkm.bin -s /usr/local/share/tkm/tkmconfig.xsd
|
||||
moon::cat /etc/ipsec.conf
|
||||
moon::tkm_keymanager -c /etc/tkm/tkm.bin -k /etc/tkm/moonKey.der -r /etc/tkm/strongswanCert.der >/tmp/tkm.log 2>&1 &
|
||||
moon::expect-file /tmp/tkm.rpc.ike
|
||||
moon::DAEMON_NAME=charon-tkm ipsec start
|
||||
sun::ipsec start
|
||||
sun::expect-connection host-host
|
||||
moon::DAEMON_NAME=charon-tkm expect-connection conn1
|
||||
moon::DAEMON_NAME=charon-tkm ipsec up conn1
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="moon winnetou sun"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="m-w-s.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="sun"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon sun"
|
|
@ -0,0 +1,3 @@
|
|||
A connection between the hosts <b>moon</b> and <b>sun</b> is set up. The host
|
||||
<b>moon</b> uses the Trusted Key Manager (TKM) and is the responder of the
|
||||
transport connection. The authentication is based on X.509 certificates.
|
|
@ -0,0 +1,12 @@
|
|||
moon::ipsec stroke status 2> /dev/null::conn1.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
||||
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=1::YES
|
||||
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
||||
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
||||
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
||||
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
||||
moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
<tkmconfig>
|
||||
<local_identity id="1">
|
||||
<identity>moon.strongswan.org</identity>
|
||||
<certificate>moonCert.pem</certificate>
|
||||
</local_identity>
|
||||
<policy id="1">
|
||||
<mode>transport</mode>
|
||||
<local>
|
||||
<identity_id>1</identity_id>
|
||||
<ip>192.168.0.1</ip>
|
||||
</local>
|
||||
<remote>
|
||||
<identity>sun.strongswan.org</identity>
|
||||
<ip>192.168.0.2</ip>
|
||||
</remote>
|
||||
<lifetime>
|
||||
<soft>30</soft>
|
||||
<hard>60</hard>
|
||||
</lifetime>
|
||||
</policy>
|
||||
</tkmconfig>
|
|
@ -0,0 +1,21 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev2
|
||||
|
||||
conn host-host
|
||||
left=PH_IP_SUN
|
||||
leftcert=sunCert.pem
|
||||
leftid=sun.strongswan.org
|
||||
right=PH_IP_MOON
|
||||
rightid=moon.strongswan.org
|
||||
ike=aes256-sha512-modp4096!
|
||||
esp=aes256-sha512-modp4096!
|
||||
auto=add
|
||||
type=transport
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
moon::DAEMON_NAME=charon-tkm ipsec stop
|
||||
moon::killall tkm_keymanager
|
||||
moon::rm -f /tmp/tkm.rpc.ike /tmp/tkm.rpc.ees /tmp/tkm.log
|
||||
sun::ipsec stop
|
|
@ -0,0 +1,10 @@
|
|||
moon::rm /etc/ipsec.secrets
|
||||
moon::tkm_cfgtool -c /etc/tkm/tkm.conf -i /etc/ipsec.conf -t /etc/tkm/tkm.bin -s /usr/local/share/tkm/tkmconfig.xsd
|
||||
moon::cat /etc/ipsec.conf
|
||||
moon::tkm_keymanager -c /etc/tkm/tkm.bin -k /etc/tkm/moonKey.der -r /etc/tkm/strongswanCert.der >/tmp/tkm.log 2>&1 &
|
||||
moon::expect-file /tmp/tkm.rpc.ike
|
||||
moon::DAEMON_NAME=charon-tkm ipsec start
|
||||
sun::ipsec start
|
||||
sun::expect-connection host-host
|
||||
moon::DAEMON_NAME=charon-tkm expect-connection conn1
|
||||
sun::ipsec up host-host
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="moon winnetou sun"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="m-w-s.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="sun"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon sun"
|
|
@ -0,0 +1,5 @@
|
|||
A transport connection between the hosts <b>moon</b> and <b>sun</b> is set up.
|
||||
The host <b>moon</b> starts the Trusted Key Manager (TKM) and the Ada XFRM
|
||||
proxy, which relays XFRM kernel messages to charon. The authentication is based
|
||||
on X.509 certificates. The connection is initiated by a ping from <b>moon</b> to
|
||||
<b>sun</b>.
|
|
@ -0,0 +1,13 @@
|
|||
moon::ipsec stroke status 2> /dev/null::conn1.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
||||
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
||||
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=1::YES
|
||||
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
||||
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
||||
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
||||
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
||||
moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
|
||||
moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
<tkmconfig>
|
||||
<local_identity id="1">
|
||||
<identity>moon.strongswan.org</identity>
|
||||
<certificate>moonCert.pem</certificate>
|
||||
</local_identity>
|
||||
<policy id="1">
|
||||
<mode>transport</mode>
|
||||
<local>
|
||||
<identity_id>1</identity_id>
|
||||
<ip>192.168.0.1</ip>
|
||||
</local>
|
||||
<remote>
|
||||
<identity>sun.strongswan.org</identity>
|
||||
<ip>192.168.0.2</ip>
|
||||
</remote>
|
||||
<lifetime>
|
||||
<soft>30</soft>
|
||||
<hard>60</hard>
|
||||
</lifetime>
|
||||
</policy>
|
||||
</tkmconfig>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue