diff --git a/0001-restore-registration-algorithm-order.bug897512.patch b/0001-restore-registration-algorithm-order.bug897512.patch new file mode 100644 index 0000000..eb4ad60 --- /dev/null +++ b/0001-restore-registration-algorithm-order.bug897512.patch @@ -0,0 +1,413 @@ +From 76ad8a6f4c83c999b9eb6d1a3506b1a8e593307e Mon Sep 17 00:00:00 2001 +From: Tobias Brunner +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, ¤t)) + { +- 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 . ++ * ++ * 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 ++ ++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 + diff --git a/README.SUSE b/README.SUSE index ae2311b..b0fe2e6 100644 --- a/README.SUSE +++ b/README.SUSE @@ -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... + diff --git a/fips-enforce.conf b/fips-enforce.conf new file mode 100644 index 0000000..637b5c8 --- /dev/null +++ b/fips-enforce.conf @@ -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 +} + diff --git a/fipscheck.sh.in b/fipscheck.sh.in new file mode 100644 index 0000000..54c989c --- /dev/null +++ b/fipscheck.sh.in @@ -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 . +# +# Author: Marius Tomaschewski +# +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 + diff --git a/strongswan-fips-disablegcrypt.patch b/strongswan-fips-disablegcrypt.patch deleted file mode 100644 index 516aa3d..0000000 --- a/strongswan-fips-disablegcrypt.patch +++ /dev/null @@ -1,15 +0,0 @@ -References: fate#316931 - -Index: strongswan-5.1.3/conf/plugins/gcrypt.conf -=================================================================== ---- strongswan-5.1.3.orig/conf/plugins/gcrypt.conf -+++ strongswan-5.1.3/conf/plugins/gcrypt.conf -@@ -2,7 +2,7 @@ gcrypt { - - # Whether to load the plugin. Can also be an integer to increase the - # priority of this plugin. -- load = yes -+ load = no - - # Use faster random numbers in gcrypt; for testing only, produces weak keys! - # quick_random = no diff --git a/strongswan.changes b/strongswan.changes index f6d144b..eb5afb9 100644 --- a/strongswan.changes +++ b/strongswan.changes @@ -1,3 +1,47 @@ +------------------------------------------------------------------- +Tue Nov 25 11:22:06 UTC 2014 - mt@suse.de + +- Updated strongswan-hmac package description (bsc#856322). + +------------------------------------------------------------------- +Fri Nov 21 12:03:59 UTC 2014 - mt@suse.de + +- Disabled explicit gpg validation; osc source_validator does it. +- Guarded fipscheck and hmac package in the spec file for >13.1. + +------------------------------------------------------------------- +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 + +- Re-enabled gcrypt plugin and reverted to not enforce fips again + as this breaks gcrypt and openssl plugins when the fips pattern + option is not installed (fate#316931,bnc#856322). + [- strongswan-fips-disablegcrypt.patch] +- Added empty strongswan-hmac package supposed to provide fips hmac + files and enforce fips compliant operation later (bnc#856322). +- Cleaned up conditional build flags in the rpm spec file. + ------------------------------------------------------------------- Thu Jul 3 13:39:45 UTC 2014 - meissner@suse.com diff --git a/strongswan.spec b/strongswan.spec index cc7e7e1..0807214 100644 --- a/strongswan.spec +++ b/strongswan.spec @@ -31,16 +31,27 @@ Release: 0 %else %bcond_with tests %endif -%if 0%{suse_version} > 1110 -%bcond_without mysql +%if 0%{suse_version} > 1310 +%bcond_without fipscheck %else -%bcond_with mysql +%bcond_with fipscheck +%endif +%ifarch %{ix86} ppc64le +%bcond_without integrity +%else +%bcond_with integrity %endif %if 0%{suse_version} > 1110 +%bcond_without farp +%bcond_without afalg +%bcond_without mysql %bcond_without sqlite %bcond_without gcrypt %bcond_without nm %else +%bcond_with farp +%bcond_with afalg +%bcond_with mysql %bcond_with sqlite %bcond_with gcrypt %bcond_with nm @@ -61,16 +72,23 @@ Source2: %{name}.init.in Source3: %{name}-%{version}-rpmlintrc Source4: README.SUSE Source5: %{name}.keyring +%if %{with fipscheck} +Source6: fipscheck.sh.in +Source7: fips-enforce.conf +%endif Patch1: %{name}_modprobe_syslog.patch Patch2: %{name}_ipsec_service.patch -Patch3: %{name}-fips-disablegcrypt.patch +%if %{with fipscheck} +Patch3: %{name}_fipscheck.patch +Patch4: %{name}_fipsfilter.patch +%endif +Patch5: 0001-restore-registration-algorithm-order.bug897512.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: bison BuildRequires: curl-devel BuildRequires: flex BuildRequires: gmp-devel BuildRequires: gperf -BuildRequires: gpg-offline BuildRequires: libcap-devel BuildRequires: libopenssl-devel BuildRequires: libsoup-devel @@ -91,11 +109,21 @@ BuildRequires: libgcrypt-devel BuildRequires: NetworkManager-devel %endif %if %{with systemd} -BuildRequires: pkgconfig(systemd) +%{?systemd_requires} %endif BuildRequires: iptables +%if %{with systemd} %{!?_rundir: %global _rundir /run} %{!?_tmpfilesdir: %global _tmpfilesdir /usr/lib/tmpfiles.d} +%else +%{!?_rundir: %global _rundir /var/run} +%endif +BuildRequires: autoconf +BuildRequires: automake +%if %{with fipscheck} +BuildRequires: fipscheck +%endif +BuildRequires: libtool %description StrongSwan is an OpenSource IPsec-based VPN Solution for Linux @@ -161,6 +189,24 @@ StrongSwan is an OpenSource IPsec-based VPN Solution for Linux This package provides the strongswan library and plugins. +%if %{with fipscheck} + +%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 +The package provides HMAC hash files for FIPS-140-2 integrity checks, +a config file disabling alternative algorithm implementations and a +_fipscheck helper script preforming the integrity checks before e.g. +"ipsec start" action is executed, when FIPS-140-2 compliant operation +mode is enabled. + +%endif + %package ipsec Summary: OpenSource IPsec-based VPN Solution Group: Productivity/Networking/Security @@ -240,39 +286,58 @@ and the load testing plugin for IKEv2 daemon. %endif %prep -%gpg_verify %{S:1} %setup -q -n %{name}-%{upstream_version} %patch1 -p0 %patch2 -p0 -%patch3 -p1 +%if %{with fipscheck} +%patch3 -p0 +%patch4 -p1 +%endif +%patch5 -p1 sed -e 's|@libexecdir@|%_libexecdir|g' \ < $RPM_SOURCE_DIR/strongswan.init.in \ > strongswan.init +%if %{with fipscheck} +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 +%endif %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 \ - --enable-conftest \ +%if %{with integrity} --enable-integrity-test \ +%endif --with-capabilities=libcap \ --with-plugindir=%{strongswan_plugins} \ - --with-fips=2 \ --with-resolv-conf=%{_rundir}/%{name}/resolv.conf \ --with-piddir=%{_rundir}/%{name} \ +%if %{with systemd} + --with-systemdsystemunitdir=%{_unitdir} \ +%endif --enable-pkcs11 \ --enable-openssl \ --enable-agent \ +%if %{with gcrypt} --enable-gcrypt \ +%else + --disable-gcrypt \ +%endif --enable-blowfish \ --enable-ctr \ --enable-ccm \ --enable-gcm \ --enable-unity \ --enable-md4 \ +%if %{with afalg} --enable-af-alg \ +%endif --enable-eap-sim \ --enable-eap-sim-file \ --enable-eap-sim-pcsc \ @@ -305,7 +370,9 @@ export RPM_OPT_FLAGS CFLAGS --enable-imv-scanner \ --enable-ha \ --enable-dhcp \ +%if %{with farp} --enable-farp \ +%endif --enable-smp \ --enable-sql \ --enable-attr-sql \ @@ -322,15 +389,13 @@ export RPM_OPT_FLAGS CFLAGS %if %{with sqlite} --enable-sqlite \ %endif -%if %{with gcrypt} - --enable-gcrypt \ -%endif %if %{with nm} --enable-nm \ %else --disable-nm \ %endif %if %{with tests} + --enable-conftest \ --enable-load-tester \ --enable-test-vectors \ %endif @@ -344,14 +409,44 @@ make %{?_smp_mflags:%_smp_mflags} export RPM_BUILD_ROOT install -d -m755 ${RPM_BUILD_ROOT}%{_sbindir}/ install -d -m755 ${RPM_BUILD_ROOT}%{_sysconfdir}/ipsec.d/ -%if ! %{with systemd} +%if %{with systemd} +ln -sf %_sbindir/service ${RPM_BUILD_ROOT}%_sbindir/rcstrongswan +%else install -d -m755 ${RPM_BUILD_ROOT}%{_sysconfdir}/init.d/ 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 # @@ -362,6 +457,12 @@ cat << EOT > ${RPM_BUILD_ROOT}%{_sysconfdir}/ipsec.secrets # EOT # +%if ! %{with mysql} +rm -f $RPM_BUILD_ROOT%{strongswan_templates}/database/sql/mysql.sql +%endif +%if ! %{with sqlite} +rm -f $RPM_BUILD_ROOT%{strongswan_templates}/database/sql/sqlite.sql +%endif rm -f $RPM_BUILD_ROOT%{strongswan_libdir}/lib{charon,hydra,strongswan,pttls}.so rm -f $RPM_BUILD_ROOT%{strongswan_libdir}/lib{radius,simaka,tls,tnccs,imcv}.so find $RPM_BUILD_ROOT%{strongswan_libdir} -type f -name "*.la" -delete @@ -372,26 +473,62 @@ install -c -m644 TODO NEWS README COPYING LICENSE \ ${RPM_BUILD_ROOT}%{strongswan_docdir}/ install -c -m644 ${RPM_SOURCE_DIR}/README.SUSE \ ${RPM_BUILD_ROOT}%{strongswan_docdir}/ - +%if %{with systemd} %{__install} -d -m 0755 %{buildroot}%{_tmpfilesdir} echo 'd %{_rundir}/%{name} 0770 root root' > %{buildroot}%{_tmpfilesdir}/%{name}.conf +%endif +%if %{with fipscheck} +# +# 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 +}} +%endif -%post libs0 -p /sbin/ldconfig +%post libs0 +/sbin/ldconfig +%{?tmpfiles_create:%tmpfiles_create %{_tmpfilesdir}/%{name}.conf} +%{!?tmpfiles_create:test -d %{_rundir}/%{name} || %{__mkdir_p} %{_rundir}/%{name}} %postun libs0 -p /sbin/ldconfig %pre ipsec +%if %{with systemd} %service_add_pre %{name}.service +%endif %post ipsec -%if ! %{with systemd} +%if %{with systemd} +%service_add_post %{name}.service +%else %{fillup_and_insserv ipsec} %endif -%{?tmpfiles_create: %tmpfiles_create %{_tmpfilesdir}/%{name}.conf } -%service_add_post %{name}.service %preun ipsec -%if ! %{with systemd} +%if %{with systemd} +%service_del_preun %{name}.service +%else %{stop_on_removal ipsec} %endif if test -s %{_sysconfdir}/ipsec.secrets.rpmsave ; then @@ -402,20 +539,38 @@ if test -s %{_sysconfdir}/ipsec.conf.rpmsave ; then cp -p --backup=numbered %{_sysconfdir}/ipsec.conf.rpmsave \ %{_sysconfdir}/ipsec.conf.rpmsave.old fi -%service_del_preun %{name}.service %postun ipsec -%if ! %{with systemd} +%if %{with systemd} +%service_del_postun %{name}.service +%else %{insserv_cleanup} %endif -%service_del_postun %{name}.service - %files %defattr(-,root,root) %dir %{strongswan_docdir} %{strongswan_docdir}/README.SUSE +%if %{with fipscheck} + +%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 + +%endif + %files ipsec %defattr(-,root,root) %config(noreplace) %attr(600,root,root) %{_sysconfdir}/ipsec.conf @@ -431,6 +586,7 @@ fi %dir %attr(700,root,root) %{_sysconfdir}/ipsec.d/private %if %{with systemd} %{_unitdir}/strongswan.service +%{_sbindir}/rcstrongswan %else %config %{_sysconfdir}/init.d/ipsec %{_sbindir}/rcipsec @@ -446,7 +602,9 @@ fi %{_libexecdir}/ipsec/_copyright %{_libexecdir}/ipsec/_updown %{_libexecdir}/ipsec/_updown_espmark +%if %{with test} %{_libexecdir}/ipsec/conftest +%endif %{_libexecdir}/ipsec/duplicheck %{_libexecdir}/ipsec/pool %{_libexecdir}/ipsec/pt-tls-client @@ -459,7 +617,6 @@ fi %dir %{strongswan_plugins} %{strongswan_plugins}/libstrongswan-stroke.so %{strongswan_plugins}/libstrongswan-updown.so -%{_tmpfilesdir}/%{name}.conf %files doc %defattr(-,root,root) @@ -477,6 +634,9 @@ fi %files libs0 %defattr(-,root,root) +%if %{with systemd} +%{_tmpfilesdir}/%{name}.conf +%endif %config(noreplace) %attr(600,root,root) %{_sysconfdir}/strongswan.conf %dir %{strongswan_configs} %dir %{strongswan_configs}/charon @@ -489,7 +649,9 @@ fi %config(noreplace) %attr(600,root,root) %{strongswan_configs}/tools.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/addrblock.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/aes.conf +%if %{with afalg} %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/af-alg.conf +%endif %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/agent.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/attr.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/attr-sql.conf @@ -523,10 +685,14 @@ fi %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/eap-tls.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/eap-tnc.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/eap-ttls.conf +%if %{with farp} %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/farp.conf +%endif %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/fips-prf.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/gcm.conf +%if %{with gcrypt} %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/gcrypt.conf +%endif %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/gmp.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/ha.conf %config(noreplace) %attr(600,root,root) %{strongswan_configs}/charon/hmac.conf @@ -573,7 +739,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.* @@ -591,7 +759,9 @@ fi %dir %{strongswan_plugins} %{strongswan_plugins}/libstrongswan-addrblock.so %{strongswan_plugins}/libstrongswan-aes.so +%if %{with afalg} %{strongswan_plugins}/libstrongswan-af-alg.so +%endif %{strongswan_plugins}/libstrongswan-agent.so %{strongswan_plugins}/libstrongswan-attr.so %{strongswan_plugins}/libstrongswan-attr-sql.so @@ -625,7 +795,9 @@ fi %{strongswan_plugins}/libstrongswan-eap-tls.so %{strongswan_plugins}/libstrongswan-eap-tnc.so %{strongswan_plugins}/libstrongswan-eap-ttls.so +%if %{with farp} %{strongswan_plugins}/libstrongswan-farp.so +%endif %{strongswan_plugins}/libstrongswan-fips-prf.so %{strongswan_plugins}/libstrongswan-gcm.so %if %{with gcrypt} @@ -685,7 +857,9 @@ fi %{strongswan_templates}/config/strongswan.conf %{strongswan_templates}/config/plugins/addrblock.conf %{strongswan_templates}/config/plugins/aes.conf +%if %{with afalg} %{strongswan_templates}/config/plugins/af-alg.conf +%endif %{strongswan_templates}/config/plugins/agent.conf %{strongswan_templates}/config/plugins/attr-sql.conf %{strongswan_templates}/config/plugins/attr.conf @@ -719,10 +893,14 @@ fi %{strongswan_templates}/config/plugins/eap-tls.conf %{strongswan_templates}/config/plugins/eap-tnc.conf %{strongswan_templates}/config/plugins/eap-ttls.conf +%if %{with farp} %{strongswan_templates}/config/plugins/farp.conf +%endif %{strongswan_templates}/config/plugins/fips-prf.conf %{strongswan_templates}/config/plugins/gcm.conf +%if %{with gcrypt} %{strongswan_templates}/config/plugins/gcrypt.conf +%endif %{strongswan_templates}/config/plugins/gmp.conf %{strongswan_templates}/config/plugins/ha.conf %{strongswan_templates}/config/plugins/hmac.conf @@ -831,6 +1009,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 diff --git a/strongswan_fipscheck.patch b/strongswan_fipscheck.patch new file mode 100644 index 0000000..b49cbd0 --- /dev/null +++ b/strongswan_fipscheck.patch @@ -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" ] diff --git a/strongswan_fipsfilter.patch b/strongswan_fipsfilter.patch new file mode 100644 index 0000000..81eee37 --- /dev/null +++ b/strongswan_fipsfilter.patch @@ -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 + #include + #include ++#include ++#include ++#include ++#include ++#include + + 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; + } +