AC_ARG_ENABLE(self-checks,
AS_HELP_STRING([--enable-self-checks], [enable self checking functionality]),
enable_self_checks=$enableval, enable_self_checks=no)
+
+AC_ARG_ENABLE(fips140-mode,
+ AS_HELP_STRING([--enable-fips140-mode], [enable FIPS140-2 mode (implies self checks)]),
+ enable_fips=$enableval, enable_fips=no)
+AM_CONDITIONAL(ENABLE_FIPS140, test "$enable_fips" = "yes")
+if [ test "$enable_fips" = "yes" ];then
+ enable_self_checks=yes
+ AC_DEFINE([ENABLE_FIPS140], 1, [Enable FIPS140-2 mode])
+fi
+
AM_CONDITIONAL(ENABLE_SELF_CHECKS, test "$enable_self_checks" = "yes")
if [ test "$enable_self_checks" = "yes" ];then
AC_DEFINE([ENABLE_SELF_CHECKS], 1, [Self checks are included in the library])
RSA-EXPORT compat: $ac_enable_rsa_export
Unicode support: $ac_have_unicode
Self checks: $enable_self_checks
+ FIPS140 mode: $enable_fips
])
AC_MSG_NOTICE([Optional applications:
gnutls_rsa_export.c gnutls_helper.c gnutls_supplemental.c \
random.c crypto-api.c gnutls_privkey.c gnutls_pcert.c \
gnutls_pubkey.c locks.c gnutls_dtls.c system_override.c \
- crypto-backend.c verify-tofu.c pin.c tpm.c
+ crypto-backend.c verify-tofu.c pin.c tpm.c fips.c
if ENABLE_SELF_CHECKS
COBJECTS += crypto-selftests.c crypto-selftests-pk.c
gnutls_state.h gnutls_x509.h crypto-backend.h \
gnutls_srp.h auth/srp.h auth/srp_passwd.h \
gnutls_helper.h gnutls_supplemental.h crypto.h random.h system.h\
- locks.h gnutls_mbuffers.h gnutls_ecc.h pin.h
+ locks.h gnutls_mbuffers.h gnutls_ecc.h pin.h fips.h
if ENABLE_PKCS11
HFILES += pkcs11_int.h
--- /dev/null
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef ENABLE_FIPS140
+
+# include <gnutls_int.h>
+# include <gnutls/gnutls.h>
+# include <unistd.h>
+
+unsigned int _gnutls_fips_mode = STATE_POWERON;
+
+unsigned _gnutls_fips_mode_enabled(void)
+{
+ /* FIXME: There are some subtle differences here. Check it out later */
+ if (access("/proc/sys/crypto/fips_enabled", R_OK) == 0 &&
+ access("/etc/system-fips", R_OK) == 0)
+ return 1;
+
+ return 0;
+}
+
+int _gnutls_fips_perform_self_checks(void)
+{
+ _gnutls_switch_fips_state(FIPS_STATE_SELFTEST);
+
+ /* Tests the FIPS algorithms */
+
+ /* ciphers */
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_192_CBC);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_GCM);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ /* MAC (includes message digest test) */
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_MD5);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ /* PK */
+ ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ ret = gnutls_pk_self_test(0, GNUTLS_PK_ECDSA);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
+ return 0;
+error:
+ _gnutls_switch_fips_state(FIPS_STATE_ERROR);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERR);
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef FIPS_H
+# define FIPS_H
+
+#include <gnutls/gnutls.h>
+
+typedef enum {
+ FIPS_STATE_POWERON,
+ FIPS_STATE_INIT,
+ FIPS_STATE_SELFTEST,
+ FIPS_STATE_OPERATIONAL,
+ FIPS_STATE_ERROR,
+ FIPS_STATE_SHUTDOWN
+} gnutls_fips_state_t;
+
+#ifdef ENABLE_FIPS140
+
+/* do not access directly */
+extern unsigned int _gnutls_fips_mode;
+
+inline static
+void _gnutls_switch_fips_state(gnutls_fips_state_t state)
+{
+ _gnutls_fips_mode = state;
+}
+
+inline static gnutls_fips_state_t _gnutls_get_fips_state(void)
+{
+ return _gnutls_fips_mode;
+}
+
+int _gnutls_fips_perform_self_checks(void);
+unsigned _gnutls_fips_mode_enabled(void);
+
+# define FAIL_IF_FIPS_ERROR \
+ if (_gnutls_get_fips_state() != FIPS_STATE_OPERATIONAL) return GNUTLS_E_LIB_IN_ERROR_STATE
+
+void _gnutls_switch_fips_state(gnutls_fips_state_t state);
+
+#else
+
+# define _gnutls_switch_fips_state(x) 0
+# define _gnutls_get_fips_state() STATE_OPERATIONAL
+# define FAIL_IF_FIPS_ERROR 0
+# define _gnutls_fips_perform_self_checks() 0
+# define _gnutls_fips_mode_enabled() 0
+#endif
+
+#endif /* FIPS_H */
#include <gnutls_datum.h>
#include <gnutls/crypto.h>
#include <crypto.h>
+#include <fips.h>
#include <algorithms.h>
#define SR(x, cleanup) if ( (x)<0 ) { \
if (unlikely(e == NULL || e->id == GNUTLS_CIPHER_NULL))
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ FAIL_IF_FIPS_ERROR;
handle->e = e;
if (unlikely(e == NULL))
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ FAIL_IF_FIPS_ERROR;
+
memset(handle, 0, sizeof(*handle));
if (e->id != GNUTLS_CIPHER_NULL) {
ERROR_ENTRY(N_
("No common application protocol could be negotiated."),
GNUTLS_E_NO_APPLICATION_PROTOCOL, 1),
+ ERROR_ENTRY(N_("Error while performing self checks."),
+ GNUTLS_E_SELF_TEST_ERROR, 1),
+ ERROR_ENTRY(N_("There is no self test for this algorithm."),
+ GNUTLS_E_NO_SELF_TEST, 1),
+ ERROR_ENTRY(N_("An error has been detected in the library and cannot continue operations."),
+ GNUTLS_E_LIB_IN_ERROR_STATE, 1),
{NULL, NULL, 0, 0}
};
#include <system.h>
#include <accelerated/cryptodev.h>
#include <accelerated/accelerated.h>
+#include <fips.h>
#include "sockets.h"
#include "gettext.h"
if (_gnutls_init++)
goto out;
+
+ _gnutls_switch_fips_state(FIPS_STATE_INIT);
e = getenv("GNUTLS_DEBUG_LEVEL");
if (e != NULL) {
#endif
_gnutls_cryptodev_init();
+
+ if (_gnutls_fips_mode_enabled()) {
+ result = _gnutls_fips_perform_self_checks();
+ if (result < 0) {
+ gnutls_assert();
+ goto out;
+ }
+ _gnutls_switch_fips_state(FIPS_STATE_OPERATIONAL);
+ }
- out:
+out:
return result;
}
#include <gnutls_hash_int.h>
#include <gnutls_errors.h>
#include <algorithms.h>
+#include <fips.h>
int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
{
int result;
const gnutls_crypto_digest_st *cc = NULL;
+ FAIL_IF_FIPS_ERROR;
+
dig->e = e;
/* check if a digest has been registered
{
int ret;
const gnutls_crypto_digest_st *cc = NULL;
+
+ FAIL_IF_FIPS_ERROR;
/* check if a digest has been registered
*/
int ret;
const gnutls_crypto_mac_st *cc = NULL;
+ FAIL_IF_FIPS_ERROR;
+
/* check if a digest has been registered
*/
cc = _gnutls_get_crypto_mac(algorithm);
int result;
const gnutls_crypto_mac_st *cc = NULL;
+ FAIL_IF_FIPS_ERROR;
+
mac->e = e;
mac->mac_len = _gnutls_mac_get_algo_len(e);
uint8_t ipad[48];
int padsize, result;
+ FAIL_IF_FIPS_ERROR;
+
padsize = get_padsize((gnutls_digest_algorithm_t) e->id);
if (padsize == 0) {
gnutls_assert();
#include <openpgp/gnutls_openpgp.h>
#include <gnutls_sig.h>
#include <algorithms.h>
+#include <fips.h>
#include <abstract_int.h>
/**
**/
int gnutls_privkey_init(gnutls_privkey_t * key)
{
+ FAIL_IF_FIPS_ERROR;
+
*key = gnutls_calloc(1, sizeof(struct gnutls_privkey_st));
if (*key == NULL) {
gnutls_assert();
#include <x509/common.h>
#include <x509_b64.h>
#include <abstract_int.h>
+#include <fips.h>
#include <gnutls_ecc.h>
**/
int gnutls_pubkey_init(gnutls_pubkey_t * key)
{
+ FAIL_IF_FIPS_ERROR;
+
*key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st));
if (*key == NULL) {
gnutls_assert();
#include <gnutls_extensions.h>
#include <system.h>
#include <random.h>
+#include <fips.h>
#include <gnutls/dtls.h>
/* These should really be static, but src/tests.c calls them. Make
{
int ret;
record_parameters_st *epoch;
+
+ FAIL_IF_FIPS_ERROR;
*session = gnutls_calloc(1, sizeof(struct gnutls_session_int));
if (*session == NULL)
#define GNUTLS_E_SELF_TEST_ERROR -400
#define GNUTLS_E_NO_SELF_TEST -401
+#define GNUTLS_E_LIB_IN_ERROR_STATE -402
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
#include <pkcs11_int.h>
#include <gnutls_sig.h>
#include <gnutls_pk.h>
+#include <fips.h>
#include <p11-kit/uri.h>
struct gnutls_pkcs11_privkey_st {
**/
int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
{
+ FAIL_IF_FIPS_ERROR;
+
*key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
if (*key == NULL) {
gnutls_assert();
#include <gnutls_int.h>
#include <gnutls_errors.h>
#include <random.h>
+#include <fips.h>
void *gnutls_rnd_ctx;
**/
int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
{
+ FAIL_IF_FIPS_ERROR;
return _gnutls_rnd(level, data, len);
}
#include <algorithms.h>
#include <abstract_int.h>
#include <x509/x509_int.h>
+#include <fips.h>
#define MAX_STRING_LEN 512
**/
int gnutls_x509_crl_init(gnutls_x509_crl_t * crl)
{
+ FAIL_IF_FIPS_ERROR;
+
*crl = gnutls_calloc(1, sizeof(gnutls_x509_crl_int));
if (*crl) {
int gnutls_x509_crq_init(gnutls_x509_crq_t * crq)
{
int result;
+
+ FAIL_IF_FIPS_ERROR;
*crq = gnutls_calloc(1, sizeof(gnutls_x509_crq_int));
if (!*crq)
**/
int gnutls_x509_privkey_init(gnutls_x509_privkey_t * key)
{
+ FAIL_IF_FIPS_ERROR;
+
*key = gnutls_calloc(1, sizeof(gnutls_x509_privkey_int));
if (*key) {
gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
unsigned int size)
{
- gnutls_x509_trust_list_t tmp =
+ gnutls_x509_trust_list_t tmp;
+
+ FAIL_IF_FIPS_ERROR;
+
+ tmp =
gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
if (!tmp)
**/
int gnutls_x509_crt_init(gnutls_x509_crt_t * cert)
{
- gnutls_x509_crt_t tmp =
+ gnutls_x509_crt_t tmp;
+
+ FAIL_IF_FIPS_ERROR;
+
+ tmp =
gnutls_calloc(1, sizeof(gnutls_x509_crt_int));
int result;
#include <gnutls_num.h>
#include <gnutls/xssl.h>
#include <auth/cert.h>
+#include <fips.h>
#include "vasprintf.h"
#include <xssl.h>
int xssl_sinit(xssl_t * isb, gnutls_session_t session, unsigned int flags)
{
struct xssl_st *sb;
+
+ FAIL_IF_FIPS_ERROR;
sb = gnutls_calloc(1, sizeof(*sb));
if (sb == NULL)
gnutls_session_t session;
int ret;
unsigned len;
+
+ FAIL_IF_FIPS_ERROR;
ret = gnutls_init(&session, GNUTLS_CLIENT);
if (ret < 0)