1
0
forked from pool/strongswan

- Added generation of fips hmac hash files using fipshmac utility

and a _fipscheck script to verify binaries/libraries/plugings
  shipped in the strongswan-hmac package.
  With enabled fips in the kernel, the ipsec script will call it
  before any action or in a enforced/manual "ipsec _fipscheck" call.
  Added config file to load openssl and kernel af-alg plugins, but
  not all the other modules which provide further/alternative algs.
  Applied a filter disallowing non-approved algorithms in fips mode.
  (fate#316931,bnc#856322).
  [+ strongswan_fipscheck.patch, strongswan_fipsfilter.patch]
- Fixed file list in the optional (disabled) strongswan-test package.
- Fixed build of the strongswan built-in integrity checksum library
  and enabled building it only on architectures tested to work.
- Fix to use bug number 897048 instead 856322 in last changes entry.
- Applied an upstream patch reverting to store algorithms in the
  registration order again as ordering them by identifier caused
  weaker algorithms to be proposed first by default (bsc#897512).
  [+0001-restore-registration-algorithm-order.bug897512.patch]

OBS-URL: https://build.opensuse.org/package/show/network:vpn/strongswan?expand=0&rev=77
This commit is contained in:
Marius Tomaschewski 2014-11-21 12:01:59 +00:00 committed by Git OBS Bridge
parent ee9ed2353d
commit 9463c65a84
8 changed files with 1038 additions and 9 deletions

View File

@ -0,0 +1,413 @@
From 76ad8a6f4c83c999b9eb6d1a3506b1a8e593307e Mon Sep 17 00:00:00 2001
From: Tobias Brunner <tobias@strongswan.org>
Date: Fri, 20 Jun 2014 16:22:15 +0200
Subject: [PATCH] Merge branch 'algorithm-order'
Upstream: yes
References: bsc#897512
Restores the behavior we had before 2e22333fb (except for RNGs), that is,
algorithms are stored in the registration order again. Which is not optimal
as we must rely on plugins to register them in a sensible order, but ordering
them by identifier definitely caused weaker algorithms to be proposed first
in the default proposal, which was even worse.
---
src/libstrongswan/crypto/crypto_factory.c | 18 +-
src/libstrongswan/tests/Makefile.am | 1 +
.../tests/suites/test_crypto_factory.c | 312 +++++++++++++++++++++
src/libstrongswan/tests/tests.h | 1 +
4 files changed, 327 insertions(+), 5 deletions(-)
create mode 100644 src/libstrongswan/tests/suites/test_crypto_factory.c
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 6dea30e..96fbc0d 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -392,10 +392,10 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
/**
* Insert an algorithm entry to a list
*
- * Entries are sorted by algorithm identifier (which is important for RNGs)
- * while maintaining the order in which algorithms were added, unless they were
+ * Entries maintain the order in which algorithms were added, unless they were
* benchmarked and speed is provided, which then is used to order entries of
* the same algorithm.
+ * An exception are RNG entries, which are sorted by algorithm identifier.
*/
static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
int algo, const char *plugin_name,
@@ -403,6 +403,7 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
{
enumerator_t *enumerator;
entry_t *entry, *current;
+ bool sort = (list == this->rngs), found = FALSE;
INIT(entry,
.algo = algo,
@@ -415,12 +416,19 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &current))
{
- if (current->algo > algo)
+ if (sort && current->algo > algo)
{
break;
}
- else if (current->algo == algo && speed &&
- current->speed < speed)
+ else if (current->algo == algo)
+ {
+ if (speed > current->speed)
+ {
+ break;
+ }
+ found = TRUE;
+ }
+ else if (found)
{
break;
}
diff --git a/src/libstrongswan/tests/Makefile.am b/src/libstrongswan/tests/Makefile.am
index 331a548..0bdf2b3 100644
--- a/src/libstrongswan/tests/Makefile.am
+++ b/src/libstrongswan/tests/Makefile.am
@@ -42,6 +42,7 @@ tests_SOURCES = tests.h tests.c \
suites/test_host.c \
suites/test_hasher.c \
suites/test_crypter.c \
+ suites/test_crypto_factory.c \
suites/test_pen.c \
suites/test_asn1.c \
suites/test_asn1_parser.c \
diff --git a/src/libstrongswan/tests/suites/test_crypto_factory.c b/src/libstrongswan/tests/suites/test_crypto_factory.c
new file mode 100644
index 0000000..94f45da
--- /dev/null
+++ b/src/libstrongswan/tests/suites/test_crypto_factory.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2014 Tobias Brunner
+ * 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 "test_suite.h"
+
+#include <crypto/crypto_factory.h>
+
+static rng_t *rng_create(rng_quality_t quality)
+{
+ rng_quality_t *q = malloc_thing(rng_quality_t);
+ *q = quality;
+ return (rng_t*)q;
+}
+
+static rng_t *rng_create_weak(rng_quality_t quality)
+{
+ ck_assert(quality == RNG_WEAK);
+ return rng_create(RNG_WEAK);
+}
+
+static rng_t *rng_create_strong(rng_quality_t quality)
+{
+ ck_assert(quality <= RNG_STRONG);
+ return rng_create(RNG_STRONG);
+}
+
+static rng_t *rng_create_true(rng_quality_t quality)
+{
+ ck_assert(quality <= RNG_TRUE);
+ return rng_create(RNG_TRUE);
+}
+
+static rng_t *rng_create_true_second(rng_quality_t quality)
+{
+ fail("should never be called");
+ return rng_create(RNG_TRUE);
+}
+
+static rng_quality_t rng_weak = RNG_WEAK;
+static rng_quality_t rng_strong = RNG_STRONG;
+static rng_quality_t rng_true = RNG_TRUE;
+
+static struct {
+ rng_quality_t *exp_weak;
+ rng_quality_t *exp_strong;
+ rng_quality_t *exp_true;
+ struct {
+ rng_quality_t *q;
+ rng_constructor_t create;
+ } data[4];
+} rng_data[] = {
+ { NULL, NULL, NULL, {
+ { NULL, NULL }
+ }},
+ { &rng_weak, NULL, NULL, {
+ { &rng_weak, rng_create_weak },
+ { NULL, NULL }
+ }},
+ { &rng_strong, &rng_strong, NULL, {
+ { &rng_strong, rng_create_strong },
+ { NULL, NULL }
+ }},
+ { &rng_true, &rng_true, &rng_true, {
+ { &rng_true, rng_create_true },
+ { NULL, NULL }
+ }},
+ { &rng_true, &rng_true, &rng_true, {
+ { &rng_true, rng_create_true },
+ { &rng_true, rng_create_true_second },
+ { NULL, NULL }
+ }},
+ { &rng_weak, &rng_true, &rng_true, {
+ { &rng_weak, rng_create_weak },
+ { &rng_true, rng_create_true },
+ { NULL, NULL }
+ }},
+ { &rng_weak, &rng_strong, &rng_true, {
+ { &rng_true, rng_create_true },
+ { &rng_strong, rng_create_strong },
+ { &rng_weak, rng_create_weak },
+ { NULL, NULL }
+ }},
+ { &rng_weak, &rng_strong, &rng_true, {
+ { &rng_weak, rng_create_weak },
+ { &rng_strong, rng_create_strong },
+ { &rng_true, rng_create_true },
+ { NULL, NULL }
+ }},
+};
+
+static void verify_rng(crypto_factory_t *factory, rng_quality_t request,
+ rng_quality_t *expected)
+{
+ rng_quality_t *res;
+
+ res = (rng_quality_t*)factory->create_rng(factory, request);
+ if (!expected)
+ {
+ ck_assert(!res);
+ }
+ else
+ {
+ ck_assert(res);
+ ck_assert_int_eq(*expected, *res);
+ free(res);
+ }
+}
+
+START_TEST(test_create_rng)
+{
+ crypto_factory_t *factory;
+ int i;
+
+ factory = crypto_factory_create();
+ for (i = 0; rng_data[_i].data[i].q; i++)
+ {
+ ck_assert(factory->add_rng(factory, *rng_data[_i].data[i].q, "test",
+ rng_data[_i].data[i].create));
+ }
+ verify_rng(factory, RNG_WEAK, rng_data[_i].exp_weak);
+ verify_rng(factory, RNG_STRONG, rng_data[_i].exp_strong);
+ verify_rng(factory, RNG_TRUE, rng_data[_i].exp_true);
+ for (i = 0; rng_data[_i].data[i].q; i++)
+ {
+ factory->remove_rng(factory, rng_data[_i].data[i].create);
+ }
+ factory->destroy(factory);
+}
+END_TEST
+
+static diffie_hellman_t *dh_create(char *plugin)
+{
+ return (diffie_hellman_t*)plugin;
+}
+
+static diffie_hellman_t *dh_create_modp1024(diffie_hellman_group_t group, ...)
+{
+ ck_assert(group == MODP_1024_BIT);
+ return dh_create("plugin1");
+}
+
+static diffie_hellman_t *dh_create_modp1024_second(diffie_hellman_group_t group,
+ ...)
+{
+ ck_assert(group == MODP_1024_BIT);
+ return dh_create("plugin2");
+}
+
+static diffie_hellman_t *dh_create_modp2048(diffie_hellman_group_t group, ...)
+{
+ ck_assert(group == MODP_2048_BIT);
+ return dh_create("plugin1");
+}
+
+static diffie_hellman_t *dh_create_modp2048_second(diffie_hellman_group_t group,
+ ...)
+{
+ ck_assert(group == MODP_2048_BIT);
+ return dh_create("plugin2");
+}
+
+static struct {
+ char *exp1024;
+ char *exp2048;
+ struct {
+ diffie_hellman_group_t g;
+ dh_constructor_t create;
+ char *plugin;
+ } data[4];
+} dh_data[] = {
+ { NULL, NULL, {
+ { MODP_NONE, NULL, NULL }
+ }},
+ { "plugin1", NULL, {
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_NONE, NULL, NULL }
+ }},
+ { "plugin1", NULL, {
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_1024_BIT, dh_create_modp1024_second, "plugin2" },
+ { MODP_NONE, NULL, NULL }
+ }},
+ { "plugin2", NULL, {
+ { MODP_1024_BIT, dh_create_modp1024_second, "plugin2" },
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_NONE, NULL, NULL }
+ }},
+ { "plugin1", "plugin1", {
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+ { MODP_NONE, NULL }
+ }},
+ { "plugin1", "plugin1", {
+ { MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_NONE, NULL }
+ }},
+ { "plugin1", "plugin1", {
+ { MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+ { MODP_2048_BIT, dh_create_modp2048_second, "plugin2" },
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_NONE, NULL }
+ }},
+ { "plugin1", "plugin2", {
+ { MODP_2048_BIT, dh_create_modp2048_second, "plugin2" },
+ { MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+ { MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+ { MODP_NONE, NULL }
+ }},
+};
+
+static void verify_dh(crypto_factory_t *factory, diffie_hellman_group_t request,
+ char *expected)
+{
+ char *plugin;
+
+ plugin = (char*)factory->create_dh(factory, request);
+ if (!expected)
+ {
+ ck_assert(!plugin);
+ }
+ else
+ {
+ ck_assert(plugin);
+ ck_assert_str_eq(expected, plugin);
+ }
+}
+
+START_TEST(test_create_dh)
+{
+ enumerator_t *enumerator;
+ crypto_factory_t *factory;
+ diffie_hellman_group_t group;
+ char *plugin;
+ int i, len = 0;
+
+
+ factory = crypto_factory_create();
+ for (i = 0; dh_data[_i].data[i].g != MODP_NONE; i++)
+ {
+ ck_assert(factory->add_dh(factory, dh_data[_i].data[i].g,
+ dh_data[_i].data[i].plugin,
+ dh_data[_i].data[i].create));
+ }
+ verify_dh(factory, MODP_1024_BIT, dh_data[_i].exp1024);
+ verify_dh(factory, MODP_2048_BIT, dh_data[_i].exp2048);
+
+ len = countof(dh_data[_i].data);
+ enumerator = factory->create_dh_enumerator(factory);
+ for (i = 0; enumerator->enumerate(enumerator, &group, &plugin) && i < len;)
+ {
+ ck_assert_int_eq(dh_data[_i].data[i].g, group);
+ while (dh_data[_i].data[i].g == group)
+ { /* skip other entries by the same group */
+ i++;
+ }
+ switch (group)
+ {
+ case MODP_1024_BIT:
+ ck_assert(dh_data[_i].exp1024);
+ ck_assert_str_eq(dh_data[_i].exp1024, plugin);
+ break;
+ case MODP_2048_BIT:
+ ck_assert(dh_data[_i].exp2048);
+ ck_assert_str_eq(dh_data[_i].exp2048, plugin);
+ break;
+ default:
+ fail("unexpected DH group");
+ break;
+ }
+ }
+ ck_assert(!enumerator->enumerate(enumerator));
+ ck_assert_int_eq(dh_data[_i].data[i].g, MODP_NONE);
+ enumerator->destroy(enumerator);
+
+ for (i = 0; dh_data[_i].data[i].g != MODP_NONE; i++)
+ {
+ factory->remove_dh(factory, dh_data[_i].data[i].create);
+ }
+ factory->destroy(factory);
+}
+END_TEST
+
+Suite *crypto_factory_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("crypto-factory");
+
+ tc = tcase_create("create_rng");
+ tcase_add_loop_test(tc, test_create_rng, 0, countof(rng_data));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("create_dh");
+ tcase_add_loop_test(tc, test_create_dh, 0, countof(dh_data));
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libstrongswan/tests/tests.h b/src/libstrongswan/tests/tests.h
index 82a5137..ab0f642 100644
--- a/src/libstrongswan/tests/tests.h
+++ b/src/libstrongswan/tests/tests.h
@@ -35,6 +35,7 @@ TEST_SUITE(host_suite_create)
TEST_SUITE(printf_suite_create)
TEST_SUITE(hasher_suite_create)
TEST_SUITE(crypter_suite_create)
+TEST_SUITE(crypto_factory_suite_create)
TEST_SUITE(pen_suite_create)
TEST_SUITE(asn1_suite_create)
TEST_SUITE(asn1_parser_suite_create)
--
2.1.2

View File

@ -15,16 +15,40 @@ This requires adoption of either the "conn %default" or all other IKEv1
keyexchange=ikev1
The charon daemon in strongswan 5.x versions supports IKEv1 and IKEv2,
thus a separate pluto IKEv1 daemon is not needed / not shipped any more.
The strongswan package does no provide any files any more, but triggers
the installation of both, IKEv1 (pluto) and IKEv2 (charon) daemons and the
traditional starter scripts inclusive of the /etc/init.d/ipsec init script
and /etc/ipsec.conf file.
There is a new strongswan-nm package with a NetworkManager plugin to
control the charon IKEv2 daemon through D-Bus, designed to work using the
NetworkManager-strongswan graphical user interface.
The strongswan package does not provide any files except of this README,
but triggers the installation of the charon daemon and the "traditional"
strongswan-ipsec package providing the "ipsec" script and service.
The ipsec.service is an alias link to the "strongswan.service" systemd
service unit and created by "systemctl enable strongswan.service".
There is a new strongswan-nm package with a NetworkManager specific charon-nm
binary controlling the charon daemon through D-Bus and designed to work using
the NetworkManager-strongswan graphical user interface.
It does not depend on the traditional starter scripts, but on the IKEv2
charon daemon and plugins only.
The stongswan-hmac package provides the fips hmac hash files, a _fipscheck
script and a /etc/strongswan.d/charon/zzz_fips-enforce.conf config file,
which disables all non-openssl algorithm implementations.
When fips operation mode is enabled in the kernel using the fips=1 boot
parameter, the strongswan fips checks are executed in front of any start
action of the "ipsec" script provided by the "strongswan-ipsec" package
and a verification problem causes a failure as required by fips-140-2.
Further, it is not required to enable the fips_mode in the openssl plugin
(/etc/strongswan.d/charon/openssl.conf); the kernel entablement enables
it automatically as needed.
The "ipsec _fipscheck" command allows to execute the fips checks manually
without a check if fips is enabled (/proc/sys/crypto/fips_enabled is 1),
e.g. for testing purposes.
Have a lot of fun...

52
fips-enforce.conf Normal file
View File

@ -0,0 +1,52 @@
#
# When fips is enabled (fips=1 kernel parameter), only certified openssl
# and kernel crypto API (af-alg) algorithms are supported.
#
# The strongswan-hmac package is supposed to be used/installed when fips
# is enabled and provides the hmac hashes, a "ipsec _fipscheck" script
# verifying the components and this blacklist disabling other plugins
# providing further and/or alternative algorithm implementations.
#
gcrypt {
load = no
}
blowfish {
load = no
}
random {
load = no
}
des {
load = no
}
aes {
load = no
}
rc2 {
load = no
}
ctr {
load = no
}
cmac {
load = no
}
xcbc {
load = no
}
md4 {
load = no
}
md5 {
load = no
}
sha1 {
load = no
}
sha2 {
load = no
}
ccm {
load = no
}

69
fipscheck.sh.in Normal file
View File

@ -0,0 +1,69 @@
#! /bin/bash
#
# Copyright (C) 2014 SUSE LINUX GmbH, Nuernberg, Germany.
#
# 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.
#
# 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.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
#
# Author: Marius Tomaschewski <mt@suse.de>
#
IPSEC_DIR="@IPSEC_DIR@"
IPSEC_LIBDIR="@IPSEC_LIBDIR@"
IPSEC_BINDIR="@IPSEC_BINDIR@"
IPSEC_SBINDIR="@IPSEC_SBINDIR@"
fipscheck_bin="/usr/bin/fipscheck"
# minimal usage hint
if test $# -gt 0 ; then
echo "usage: ipsec _fipscheck" >&2
exit 2
fi
#
# "ipsec xxx" starts this script only if crypto/fips_enabled=1,
# except while a manually enforced check via "ipsec _fipscheck".
#
#read 2>/dev/null fips_enabled < /proc/sys/crypto/fips_enabled
#test "X$fips_enabled" = "X1" || exit 0
# verify that fipscheck is installed
test -x "$fipscheck_bin" || {
test "X$FIPSCHECK_DEBUG" = "Xerror" && \
echo "${0##*/}: $fipscheck_bin utility missed" >&2
exit 4
}
shopt -s nullglob
files=()
for h in ${IPSEC_DIR}/.*.hmac \
${IPSEC_LIBDIR}/.*.hmac \
${IPSEC_LIBDIR}/imcvs/.*.hmac \
${IPSEC_LIBDIR}/plugins/.*.hmac \
${IPSEC_SBINDIR}/.ipsec.hmac \
;
do
dir="${h%/*}"
name="${h##*/.}"
file="${dir}/${name%.hmac}"
# some part is not installed
test -f "${file}" && files+=("$file")
done
if test ${#files[@]} -gt 0 ; then
$fipscheck_bin ${files[@]} ; exit $?
elif test "X$FIPSCHECK_DEBUG" = "Xerror" ; then
echo "${0##*/}: unable to find any checksum/hmac file" >&2
fi
exit 3

View File

@ -1,3 +1,25 @@
-------------------------------------------------------------------
Thu Nov 20 07:43:43 UTC 2014 - mt@suse.de
- Added generation of fips hmac hash files using fipshmac utility
and a _fipscheck script to verify binaries/libraries/plugings
shipped in the strongswan-hmac package.
With enabled fips in the kernel, the ipsec script will call it
before any action or in a enforced/manual "ipsec _fipscheck" call.
Added config file to load openssl and kernel af-alg plugins, but
not all the other modules which provide further/alternative algs.
Applied a filter disallowing non-approved algorithms in fips mode.
(fate#316931,bnc#856322).
[+ strongswan_fipscheck.patch, strongswan_fipsfilter.patch]
- Fixed file list in the optional (disabled) strongswan-test package.
- Fixed build of the strongswan built-in integrity checksum library
and enabled building it only on architectures tested to work.
- Fix to use bug number 897048 instead 856322 in last changes entry.
- Applied an upstream patch reverting to store algorithms in the
registration order again as ordering them by identifier caused
weaker algorithms to be proposed first by default (bsc#897512).
[+0001-restore-registration-algorithm-order.bug897512.patch]
-------------------------------------------------------------------
Fri Sep 26 16:02:09 UTC 2014 - mt@suse.de

View File

@ -31,6 +31,11 @@ Release: 0
%else
%bcond_with tests
%endif
%ifarch %{ix86} ppc64le
%bcond_without integrity
%else
%bcond_with integrity
%endif
%if 0%{suse_version} > 1110
%bcond_without farp
%bcond_without afalg
@ -62,8 +67,13 @@ Source2: %{name}.init.in
Source3: %{name}-%{version}-rpmlintrc
Source4: README.SUSE
Source5: %{name}.keyring
Source6: fipscheck.sh.in
Source7: fips-enforce.conf
Patch1: %{name}_modprobe_syslog.patch
Patch2: %{name}_ipsec_service.patch
Patch3: %{name}_fipscheck.patch
Patch4: %{name}_fipsfilter.patch
Patch5: 0001-restore-registration-algorithm-order.bug897512.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: bison
BuildRequires: curl-devel
@ -100,6 +110,10 @@ BuildRequires: iptables
%else
%{!?_rundir: %global _rundir /var/run}
%endif
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: fipscheck
BuildRequires: libtool
%description
StrongSwan is an OpenSource IPsec-based VPN Solution for Linux
@ -168,6 +182,8 @@ This package provides the strongswan library and plugins.
%package hmac
Summary: HMAC files for FIPS-140-2 integrity
Group: Productivity/Networking/Security
Requires: fipscheck
Requires: strongswan-ipsec = %{version}
Requires: strongswan-libs0 = %{version}
%description hmac
@ -257,17 +273,27 @@ and the load testing plugin for IKEv2 daemon.
%setup -q -n %{name}-%{upstream_version}
%patch1 -p0
%patch2 -p0
%patch3 -p0
%patch4 -p1
%patch5 -p1
sed -e 's|@libexecdir@|%_libexecdir|g' \
< $RPM_SOURCE_DIR/strongswan.init.in \
> strongswan.init
sed -e 's|@IPSEC_DIR@|%{_libexecdir}/ipsec|g' \
-e 's|@IPSEC_LIBDIR@|%{_libdir}/ipsec|g' \
-e 's|@IPSEC_SBINDIR@|%{_sbindir}|g' \
-e 's|@IPSEC_BINDIR@|%{_bindir}|g' \
< $RPM_SOURCE_DIR/fipscheck.sh.in \
> _fipscheck
%build
CFLAGS="$RPM_OPT_FLAGS -W -Wall -Wno-pointer-sign -Wno-strict-aliasing -Wno-unused-parameter"
export RPM_OPT_FLAGS CFLAGS
#libtoolize --force
#autoreconf
autoreconf --force --install
%configure \
%if %{with integrity}
--enable-integrity-test \
%endif
--with-capabilities=libcap \
--with-plugindir=%{strongswan_plugins} \
--with-resolv-conf=%{_rundir}/%{name}/resolv.conf \
@ -368,8 +394,36 @@ install -m755 strongswan.init ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d/ipsec
ln -s %{_sysconfdir}/init.d/ipsec ${RPM_BUILD_ROOT}%{_sbindir}/rcipsec
%endif
#
# Ensure, plugin -> library dependencies can be resolved
# (e.g. libtls) to avoid plugin segment checksum errors.
#
LD_LIBRARY_PATH="$RPM_BUILD_ROOT-$$%{strongswan_libdir}" \
make install DESTDIR="$RPM_BUILD_ROOT"
#
# checksums are calculated during make install using the
# installed binaries/libraries... but find-debuginfo.sh
# extracts debuginfo/debugsource breaking file checksums.
# let find-debuginfo.sh run on a build root copy and then
# calculate the checksums.
#
%if %{with integrity}
%{?__debug_package:
if test -x %{_rpmconfigdir}/find-debuginfo.sh ; then
cp -a "${RPM_BUILD_ROOT}" "${RPM_BUILD_ROOT}-$$"
RPM_BUILD_ROOT="$RPM_BUILD_ROOT-$$" \
%{_rpmconfigdir}/find-debuginfo.sh \
%{?_find_debuginfo_opts} "${RPM_BUILD_ROOT}-$$"
make -C src/checksum clean
rm -f src/checksum/checksum_builder
LD_LIBRARY_PATH="$RPM_BUILD_ROOT-$$%{strongswan_libdir}" \
make -C src/checksum install DESTDIR="$RPM_BUILD_ROOT-$$"
mv "$RPM_BUILD_ROOT-$$%{strongswan_libdir}/libchecksum.so" \
"$RPM_BUILD_ROOT%{strongswan_libdir}/libchecksum.so"
rm -rf "${RPM_BUILD_ROOT}-$$"
fi
}
%endif
#
rm -f ${RPM_BUILD_ROOT}%{_sysconfdir}/ipsec.secrets
cat << EOT > ${RPM_BUILD_ROOT}%{_sysconfdir}/ipsec.secrets
#
@ -400,6 +454,32 @@ install -c -m644 ${RPM_SOURCE_DIR}/README.SUSE \
%{__install} -d -m 0755 %{buildroot}%{_tmpfilesdir}
echo 'd %{_rundir}/%{name} 0770 root root' > %{buildroot}%{_tmpfilesdir}/%{name}.conf
%endif
#
# note: keep the following, _fipscheck's and file lists in sync
#
install -c -m750 _fipscheck ${RPM_BUILD_ROOT}%{_libexecdir}/ipsec/
install -c -m644 ${RPM_SOURCE_DIR}/fips-enforce.conf \
${RPM_BUILD_ROOT}%{strongswan_configs}/charon/zzz_fips-enforce.conf
# create fips hmac hashes _after_ install post run
%{expand:%%global __os_install_post {%__os_install_post
for f in $RPM_BUILD_ROOT%{strongswan_libdir}/lib*.so.*.*.* \
$RPM_BUILD_ROOT%{strongswan_libdir}/imcvs/*.so \
$RPM_BUILD_ROOT%{strongswan_plugins}/*.so \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/charon \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/charon-nm \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/stroke \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/starter \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/pool \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/scepclient \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/pt-tls-client \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/imv_policy_manager \
$RPM_BUILD_ROOT%{_libexecdir}/ipsec/_fipscheck \
$RPM_BUILD_ROOT%{_sbindir}/ipsec \
;
do
/usr/bin/fipshmac "$f"
done
}}
%post libs0
/sbin/ldconfig
@ -449,6 +529,18 @@ fi
%files hmac
%defattr(-,root,root)
%dir %{strongswan_configs}
%dir %{strongswan_configs}/charon
%config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/zzz_fips-enforce.conf
%dir %{strongswan_libdir}
%{strongswan_libdir}/.*.hmac
%{strongswan_libdir}/imcvs/.*.hmac
%dir %{strongswan_plugins}
%{strongswan_plugins}/.*.hmac
%dir %{_libexecdir}/ipsec
%{_libexecdir}/ipsec/_fipscheck
%{_libexecdir}/ipsec/.*.hmac
%{_sbindir}/.ipsec.hmac
%files ipsec
%defattr(-,root,root)
@ -618,7 +710,9 @@ fi
%config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/xauth-pam.conf
%config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/xcbc.conf
%dir %{strongswan_libdir}
%if %{with integrity}
%{strongswan_libdir}/libchecksum.so
%endif
%{strongswan_libdir}/libcharon.so.*
%{strongswan_libdir}/libhydra.so.*
%{strongswan_libdir}/libpttls.so.*
@ -886,6 +980,18 @@ fi
%files tests
%defattr(-,root,root)
%dir %{strongswan_configs}
%dir %{strongswan_configs}/charon
%{strongswan_configs}/charon/load-tester.conf
%{strongswan_configs}/charon/test-vectors.conf
%dir %{strongswan_templates}
%dir %{strongswan_templates}/config
%dir %{strongswan_templates}/config/plugins
%{strongswan_templates}/config/plugins/load-tester.conf
%{strongswan_templates}/config/plugins/test-vectors.conf
%dir %{_libexecdir}/ipsec
%{_libexecdir}/ipsec/conftest
%{_libexecdir}/ipsec/load-tester
%dir %{strongswan_libdir}
%dir %{strongswan_plugins}
%{strongswan_plugins}/libstrongswan-load-tester.so

View File

@ -0,0 +1,89 @@
--- src/ipsec/_ipsec.in
+++ src/ipsec/_ipsec.in 2014/11/07 11:28:25
@@ -44,6 +44,26 @@ export IPSEC_DIR IPSEC_BINDIR IPSEC_SBIN
IPSEC_DISTRO="Institute for Internet Technologies and Applications\nUniversity of Applied Sciences Rapperswil, Switzerland"
+fipscheck()
+{
+ # when fips operation mode is not enabled, just report OK
+ read 2>/dev/null fips_enabled < /proc/sys/crypto/fips_enabled
+ test "X$fips_enabled" = "X1" || return 0
+
+ # complain when _fipscheck is missed
+ test -x "$IPSEC_DIR/_fipscheck" || {
+ echo "ipsec: please install strongswan-hmac package required in fips mode" >&2
+ return 4
+ }
+
+ # now execute it
+ $IPSEC_DIR/_fipscheck || {
+ rc=$?
+ echo "ipsec: strongSwan fips file integrity check failed" >&2
+ return $rc
+ }
+}
+
case "$1" in
'')
echo "Usage: $IPSEC_SCRIPT command argument ..."
@@ -166,6 +186,7 @@ rereadall|purgeocsp|listcounters|resetco
shift
if [ -e $IPSEC_CHARON_PID ]
then
+ fipscheck || exit $?
$IPSEC_STROKE "$op" "$@"
rc="$?"
fi
@@ -175,6 +196,7 @@ purgeike|purgecrls|purgecerts)
rc=7
if [ -e $IPSEC_CHARON_PID ]
then
+ fipscheck || exit $?
$IPSEC_STROKE "$1"
rc="$?"
fi
@@ -208,6 +230,7 @@ route|unroute)
fi
if [ -e $IPSEC_CHARON_PID ]
then
+ fipscheck || exit $?
$IPSEC_STROKE "$op" "$1"
rc="$?"
fi
@@ -217,6 +240,7 @@ secrets)
rc=7
if [ -e $IPSEC_CHARON_PID ]
then
+ fipscheck || exit $?
$IPSEC_STROKE rereadsecrets
rc="$?"
fi
@@ -224,6 +248,7 @@ secrets)
;;
start)
shift
+ fipscheck || exit $?
if [ -d /var/lock/subsys ]; then
touch /var/lock/subsys/ipsec
fi
@@ -297,6 +322,7 @@ up)
rc=7
if [ -e $IPSEC_CHARON_PID ]
then
+ fipscheck || exit $?
$IPSEC_STROKE up "$1"
rc="$?"
fi
@@ -332,6 +358,11 @@ esac
cmd="$1"
shift
+case $cmd in
+_fipscheck|_copyright|pki) ;;
+*) fipscheck || exit $? ;;
+esac
+
path="$IPSEC_DIR/$cmd"
if [ ! -x "$path" ]

254
strongswan_fipsfilter.patch Normal file
View File

@ -0,0 +1,254 @@
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 2ecdb4f..85767ab 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -26,6 +26,11 @@
#include <crypto/prfs/prf.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
"PROTO_NONE",
@@ -185,6 +190,130 @@ METHOD(proposal_t, strip_dh, void,
enumerator->destroy(enumerator);
}
+static bool kernel_fips_enabled(void)
+{
+ char buf[1] = { '\0' };
+ int fd;
+
+ fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
+ if (fd >= 0) {
+ while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
+ close(fd);
+ }
+ return buf[0] == '1';
+}
+
+static bool fips_enabled(void)
+{
+ static int enabled = -1;
+ if (enabled == -1)
+ enabled = kernel_fips_enabled();
+ return enabled;
+}
+
+static bool fips_filter(protocol_id_t protocol, transform_type_t type, u_int16_t alg)
+{
+ switch (protocol)
+ {
+ case PROTO_IKE:
+ case PROTO_ESP:
+ case PROTO_AH:
+ break;
+ default:
+ /* not applicable protocol */
+ return TRUE;
+ }
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ switch (alg)
+ {
+ /* crypter */
+ case ENCR_3DES:
+ case ENCR_AES_CBC:
+ case ENCR_AES_CTR:
+ /* aead */
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ case INTEGRITY_ALGORITHM:
+ switch (alg)
+ {
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA1_160:
+ case AUTH_HMAC_SHA2_256_96:
+ case AUTH_HMAC_SHA2_256_128:
+ case AUTH_HMAC_SHA2_384_192:
+ case AUTH_HMAC_SHA2_512_256:
+ case AUTH_AES_CMAC_96:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ switch (alg)
+ {
+ case PRF_HMAC_SHA1:
+ case PRF_HMAC_SHA2_256:
+ case PRF_HMAC_SHA2_384:
+ case PRF_HMAC_SHA2_512:
+ case PRF_AES128_CMAC:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ case DIFFIE_HELLMAN_GROUP:
+ switch (alg)
+ {
+ case MODP_1024_BIT:
+ case MODP_1536_BIT:
+ case MODP_2048_BIT:
+ case MODP_3072_BIT:
+ case MODP_4096_BIT:
+ case MODP_8192_BIT:
+ case MODP_1024_160:
+ case MODP_2048_224:
+ case MODP_2048_256:
+ case ECP_192_BIT:
+ case ECP_224_BIT:
+ case ECP_256_BIT:
+ case ECP_384_BIT:
+ case ECP_521_BIT:
+ case ECP_224_BP:
+ case ECP_256_BP:
+ case ECP_384_BP:
+ case ECP_512_BP:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ case EXTENDED_SEQUENCE_NUMBERS:
+ switch (alg)
+ {
+ case EXT_SEQ_NUMBERS:
+ case NO_EXT_SEQ_NUMBERS:
+ return TRUE;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ return !fips_enabled();
+}
+
/**
* Select a matching proposal from this and other, insert into selected.
*/
@@ -500,6 +629,11 @@ static bool add_string_algo(private_proposal_t *this, const char *alg)
return FALSE;
}
+ if (!fips_filter(this->protocol, token->type, token->algorithm))
+ {
+ DBG1(DBG_CFG, "algorithm '%s' not permitted in fips mode", alg);
+ return FALSE;
+ }
add_algorithm(this, token->type, token->algorithm, token->keysize);
return TRUE;
@@ -639,6 +773,8 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
{
+ if (!fips_filter(PROTO_IKE, ENCRYPTION_ALGORITHM, encryption))
+ continue;
switch (encryption)
{
case ENCR_AES_CBC:
@@ -665,6 +801,9 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
{
+ if (!fips_filter(PROTO_IKE, ENCRYPTION_ALGORITHM, encryption))
+ continue;
+
switch (encryption)
{
case ENCR_AES_CCM_ICV8:
@@ -690,6 +829,8 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
{
+ if (!fips_filter(PROTO_IKE, INTEGRITY_ALGORITHM, integrity))
+ continue;
switch (integrity)
{
case AUTH_HMAC_SHA1_96:
@@ -710,6 +851,8 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &prf, &plugin_name))
{
+ if (!fips_filter(PROTO_IKE, PSEUDO_RANDOM_FUNCTION, prf))
+ continue;
switch (prf)
{
case PRF_HMAC_SHA1:
@@ -730,6 +873,8 @@ static void proposal_add_supported_ike(private_proposal_t *this)
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &group, &plugin_name))
{
+ if (!fips_filter(PROTO_IKE, DIFFIE_HELLMAN_GROUP, group))
+ continue;
switch (group)
{
case MODP_NULL:
@@ -776,31 +921,35 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
{
private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
+#define fips_add_algorithm(this, type, alg, len) \
+ if (fips_filter(this->protocol, type, alg)) \
+ add_algorithm(this, type, alg, len);
switch (protocol)
{
case PROTO_IKE:
proposal_add_supported_ike(this);
break;
case PROTO_ESP:
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
- add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+ fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
+ fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
+ fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
+ fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
+ fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+ fips_add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
break;
case PROTO_AH:
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
- add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
+ fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+ fips_add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
break;
default:
break;
}
+#undef fips_add_algorithm
return &this->public;
}