diff --git a/ChangeLog b/ChangeLog index 805257b0..9db60784 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-05-21 Milan Broz + * Add --enable-fips for linking with fipscheck library. + * Initialize binary and library selfcheck if running in FIPS mode. + 2012-05-09 Milan Broz * Fix keyslot removal (wipe keyslot) for device with 4k hw block (1.4.0). * Allow empty cipher (cipher_null) for testing. diff --git a/configure.in b/configure.in index 55706a0e..f6ceb863 100644 --- a/configure.in +++ b/configure.in @@ -69,6 +69,16 @@ AC_ARG_ENABLE([fips], AS_HELP_STRING([--enable-fips],[enable FIPS mode restricti if test "x$with_fips" = "xyes"; then AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions]) + + if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then + AC_MSG_ERROR([Static build is not compatible with FIPS.]) + fi + + saved_LIBS=$LIBS + AC_CHECK_LIB(fipscheck, FIPSCHECK_verify, ,[AC_MSG_ERROR([You need the fipscheck library.])]) + AC_SUBST(FIPSCHECK_LIBS, $LIBS) + LIBS=$saved_LIBS + fi AC_DEFUN([NO_FIPS], [ diff --git a/lib/Makefile.am b/lib/Makefile.am index d816b788..4e16ea46 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -38,6 +38,7 @@ libcryptsetup_la_LIBADD = \ @UUID_LIBS@ \ @DEVMAPPER_LIBS@ \ @CRYPTO_LIBS@ \ + @FIPSCHECK_LIBS@ \ $(common_ldadd) @@ -54,6 +55,8 @@ libcryptsetup_la_SOURCES = \ utils_loop.h \ utils_devpath.c \ utils_wipe.c \ + utils_fips.c \ + utils_fips.h \ libdevmapper.c \ utils_dm.h \ volumekey.c \ diff --git a/lib/crypto_backend/crypto_gcrypt.c b/lib/crypto_backend/crypto_gcrypt.c index 9459fb0d..0c063770 100644 --- a/lib/crypto_backend/crypto_gcrypt.c +++ b/lib/crypto_backend/crypto_gcrypt.c @@ -37,12 +37,13 @@ struct crypt_hmac { int hash_len; }; -int crypt_backend_init(struct crypt_device *ctx __attribute__((unused))) +int crypt_backend_init(struct crypt_device *ctx) { if (crypto_backend_initialised) return 0; log_dbg("Initialising gcrypt crypto backend."); + crypt_fips_libcryptsetup_check(ctx); if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) { if (!gcry_check_version (GCRYPT_REQ_VERSION)) { return -ENOSYS; diff --git a/lib/internal.h b/lib/internal.h index 44ec5a1a..f7ae8641 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -35,6 +35,7 @@ #include "utils_crypt.h" #include "utils_loop.h" #include "utils_dm.h" +#include "utils_fips.h" /* to silent gcc -Wcast-qual for const cast */ #define CONST_CAST(x) (x)(uintptr_t) diff --git a/lib/setup.c b/lib/setup.c index 8e984906..104684ad 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1832,6 +1832,11 @@ int crypt_volume_key_get(struct crypt_device *cd, unsigned key_len; int r = -EINVAL; + if (crypt_fips_mode()) { + log_err(cd, "Function not available in FIPS mode.\n"); + return -EACCES; + } + key_len = crypt_get_volume_key_size(cd); if (key_len > *volume_key_size) { log_err(cd, _("Volume key buffer too small.\n")); diff --git a/lib/utils_fips.c b/lib/utils_fips.c new file mode 100644 index 00000000..0c56c59d --- /dev/null +++ b/lib/utils_fips.c @@ -0,0 +1,60 @@ +/* + * FIPS mode utilities + * + * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "libcryptsetup.h" +#include "utils_fips.h" +#include "config.h" + +#if !ENABLE_FIPS +int crypt_fips_mode(void) { return 0; } +void crypt_fips_libcryptsetup_check(struct crypt_device *cd) {} +void crypt_fips_self_check(struct crypt_device *cd) {} +#else +#include + +int crypt_fips_mode(void) +{ + return FIPSCHECK_kernel_fips_mode(); +} + +static void crypt_fips_verify(struct crypt_device *cd, + const char *name, const char *function) +{ + if (!crypt_fips_mode()) + return; + + if (!FIPSCHECK_verify(name, function)) { + crypt_log(cd, CRYPT_LOG_ERROR, "FIPS checksum verification failed.\n"); + exit(EXIT_FAILURE); + } + + crypt_log(cd, CRYPT_LOG_VERBOSE, "Running in FIPS mode.\n"); +} + +void crypt_fips_libcryptsetup_check(struct crypt_device *cd) +{ + crypt_fips_verify(cd, "libcryptsetup.so", "crypt_init"); +} + +void crypt_fips_self_check(struct crypt_device *cd) +{ + crypt_fips_verify(cd, NULL, NULL); +} +#endif /* ENABLE_FIPS */ diff --git a/lib/utils_fips.h b/lib/utils_fips.h new file mode 100644 index 00000000..fb38c3f3 --- /dev/null +++ b/lib/utils_fips.h @@ -0,0 +1,29 @@ +/* + * FIPS mode utilities + * + * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _UTILS_FIPS_H +#define _UTILS_FIPS_H + +struct crypt_device; + +int crypt_fips_mode(void); +void crypt_fips_libcryptsetup_check(struct crypt_device *cd); +void crypt_fips_self_check(struct crypt_device *cd); + +#endif /* _UTILS_FIPS_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 5f2524cd..532c67b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,12 +12,14 @@ INCLUDES = \ cryptsetup_SOURCES = \ $(top_builddir)/lib/utils_crypt.c \ $(top_builddir)/lib/utils_loop.c \ + $(top_builddir)/lib/utils_fips.c \ cryptsetup.c \ cryptsetup.h cryptsetup_LDADD = \ $(top_builddir)/lib/libcryptsetup.la \ - @POPT_LIBS@ + @POPT_LIBS@ \ + @FIPSCHECK_LIBS@ cryptsetup_CFLAGS = -Wall diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 2f672b85..3bc24c19 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1317,6 +1317,8 @@ int main(int argc, const char **argv) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + crypt_fips_self_check(NULL); + popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0); poptSetOtherOptionHelp(popt_context, N_("[OPTION...] ]")); diff --git a/src/cryptsetup.h b/src/cryptsetup.h index 41cb2601..5e4ae90c 100644 --- a/src/cryptsetup.h +++ b/src/cryptsetup.h @@ -27,6 +27,7 @@ #include "lib/nls.h" #include "lib/utils_crypt.h" #include "lib/utils_loop.h" +#include "lib/utils_fips.h" #define DEFAULT_CIPHER(type) (DEFAULT_##type##_CIPHER "-" DEFAULT_##type##_MODE)