]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Updated FIPS140 initialization and added a self test for it.
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 12 Nov 2013 11:46:10 +0000 (12:46 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 27 Nov 2013 10:41:42 +0000 (11:41 +0100)
12 files changed:
NEWS
build-aux/config.rpath
configure.ac
lib/Makefile.am
lib/fips.c
lib/fips.h
lib/includes/Makefile.am
lib/includes/gnutls/fips140.h [new file with mode: 0644]
lib/libgnutls.map
lib/xssl.c
tests/Makefile.am
tests/fips-test.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 4699e5b291133874f6c42b1cd63048843e381c7e..80fbed4630a032486fb707c68a9f23b17cbc74ee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ See the end for copying conditions.
 
 ** API and ABI modifications:
 gnutls_privkey_generate: Added
+gnutls_fips140_mode_enabled: Added
 
 
 * Version 3.2.6 (released 2013-10-31)
index c38b914d6be36839c83ef7f79e804e45ee9cb736..17298f2348bf0c5ce90917bf19abfb75a92ae179 100755 (executable)
@@ -2,7 +2,7 @@
 # Output a system dependent set of variables, describing how to set the
 # run time search path of shared libraries in an executable.
 #
-#   Copyright 1996-2013 Free Software Foundation, Inc.
+#   Copyright 1996-2010 Free Software Foundation, Inc.
 #   Taken from GNU libtool, 2001
 #   Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 #
@@ -25,7 +25,7 @@
 #   known workaround is to choose shorter directory names for the build
 #   directory and/or the installation directory.
 
-# All known linkers require a '.a' archive for static linking (except MSVC,
+# All known linkers require a `.a' archive for static linking (except MSVC,
 # which needs '.lib').
 libext=a
 shrext=.so
@@ -57,6 +57,13 @@ else
     aix*)
       wl='-Wl,'
       ;;
+    darwin*)
+      case $cc_basename in
+        xlc*)
+          wl='-Wl,'
+          ;;
+      esac
+      ;;
     mingw* | cygwin* | pw32* | os2* | cegcc*)
       ;;
     hpux9* | hpux10* | hpux11*)
@@ -65,7 +72,9 @@ else
     irix5* | irix6* | nonstopux*)
       wl='-Wl,'
       ;;
-    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    newsos6)
+      ;;
+    linux* | k*bsd*-gnu)
       case $cc_basename in
         ecc*)
           wl='-Wl,'
@@ -76,26 +85,17 @@ else
         lf95*)
           wl='-Wl,'
           ;;
-        nagfor*)
-          wl='-Wl,-Wl,,'
-          ;;
-        pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        pgcc | pgf77 | pgf90)
           wl='-Wl,'
           ;;
         ccc*)
           wl='-Wl,'
           ;;
-        xl* | bgxl* | bgf* | mpixl*)
-          wl='-Wl,'
-          ;;
         como)
           wl='-lopt='
           ;;
         *)
           case `$CC -V 2>&1 | sed 5q` in
-            *Sun\ F* | *Sun*Fortran*)
-              wl=
-              ;;
             *Sun\ C*)
               wl='-Wl,'
               ;;
@@ -103,24 +103,13 @@ else
           ;;
       esac
       ;;
-    newsos6)
-      ;;
-    *nto* | *qnx*)
-      ;;
     osf3* | osf4* | osf5*)
       wl='-Wl,'
       ;;
     rdos*)
       ;;
     solaris*)
-      case $cc_basename in
-        f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
-          wl='-Qoption ld '
-          ;;
-        *)
-          wl='-Wl,'
-          ;;
-      esac
+      wl='-Wl,'
       ;;
     sunos4*)
       wl='-Qoption ld '
@@ -182,14 +171,15 @@ if test "$with_gnu_ld" = yes; then
       fi
       ;;
     amigaos*)
-      case "$host_cpu" in
-        powerpc)
-          ;;
-        m68k)
-          hardcode_libdir_flag_spec='-L$libdir'
-          hardcode_minus_L=yes
-          ;;
-      esac
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we cannot use
+      # them.
+      ld_shlibs=no
       ;;
     beos*)
       if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
@@ -208,13 +198,11 @@ if test "$with_gnu_ld" = yes; then
         ld_shlibs=no
       fi
       ;;
-    haiku*)
-      ;;
     interix[3-9]*)
       hardcode_direct=no
       hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
       ;;
-    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+    gnu* | linux* | k*bsd*-gnu)
       if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
         :
       else
@@ -337,14 +325,10 @@ else
       fi
       ;;
     amigaos*)
-      case "$host_cpu" in
-        powerpc)
-          ;;
-        m68k)
-          hardcode_libdir_flag_spec='-L$libdir'
-          hardcode_minus_L=yes
-          ;;
-      esac
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs=no
       ;;
     bsdi[45]*)
       ;;
@@ -358,15 +342,24 @@ else
       ;;
     darwin* | rhapsody*)
       hardcode_direct=no
-      if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
+      if test "$GCC" = yes ; then
         :
       else
-        ld_shlibs=no
+        case $cc_basename in
+          xlc*)
+            ;;
+          *)
+            ld_shlibs=no
+            ;;
+        esac
       fi
       ;;
     dgux*)
       hardcode_libdir_flag_spec='-L$libdir'
       ;;
+    freebsd1*)
+      ld_shlibs=no
+      ;;
     freebsd2.2*)
       hardcode_libdir_flag_spec='-R$libdir'
       hardcode_direct=yes
@@ -427,8 +420,6 @@ else
       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
       hardcode_libdir_separator=:
       ;;
-    *nto* | *qnx*)
-      ;;
     openbsd*)
       if test -f /usr/libexec/ld.so; then
         hardcode_direct=yes
@@ -524,12 +515,7 @@ case "$host_os" in
     library_names_spec='$libname$shrext'
     ;;
   amigaos*)
-    case "$host_cpu" in
-      powerpc*)
-        library_names_spec='$libname$shrext' ;;
-      m68k)
-        library_names_spec='$libname.a' ;;
-    esac
+    library_names_spec='$libname.a'
     ;;
   beos*)
     library_names_spec='$libname$shrext'
@@ -548,6 +534,8 @@ case "$host_os" in
   dgux*)
     library_names_spec='$libname$shrext'
     ;;
+  freebsd1*)
+    ;;
   freebsd* | dragonfly*)
     case "$host_os" in
       freebsd[123]*)
@@ -559,9 +547,6 @@ case "$host_os" in
   gnu*)
     library_names_spec='$libname$shrext'
     ;;
-  haiku*)
-    library_names_spec='$libname$shrext'
-    ;;
   hpux9* | hpux10* | hpux11*)
     case $host_cpu in
       ia64*)
@@ -597,7 +582,7 @@ case "$host_os" in
     ;;
   linux*oldld* | linux*aout* | linux*coff*)
     ;;
-  linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  linux* | k*bsd*-gnu)
     library_names_spec='$libname$shrext'
     ;;
   knetbsd*-gnu)
@@ -609,7 +594,7 @@ case "$host_os" in
   newsos6)
     library_names_spec='$libname$shrext'
     ;;
-  *nto* | *qnx*)
+  nto-qnx*)
     library_names_spec='$libname$shrext'
     ;;
   openbsd*)
@@ -640,9 +625,6 @@ case "$host_os" in
   sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
     library_names_spec='$libname$shrext'
     ;;
-  tpf*)
-    library_names_spec='$libname$shrext'
-    ;;
   uts4*)
     library_names_spec='$libname$shrext'
     ;;
index 7681b56b79620a20fdc208712e434bf1754f1479..18b03117d71dd71294b8160e38509b44f4db05a3 100644 (file)
@@ -131,8 +131,20 @@ AC_ARG_ENABLE(fips140-mode,
     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])
+  AC_LIB_HAVE_LINKFLAGS(dl,, [#include <dlfcn.h>], [dladdr (0, 0);])
+  if test "x$HAVE_LIBDL" = "xyes";then
+    enable_self_checks=yes
+    AC_DEFINE([ENABLE_FIPS140], 1, [Enable FIPS140-2 mode])
+
+    AC_SUBST([FIPS140_LIBS], $LIBDL)
+  else
+    enable_fips=no
+    AC_MSG_WARN([[
+*** 
+*** This system is not supported in FIPS140 mode.
+*** libdl and dladdr() are required.
+*** ]])
+  fi
 fi
 
 AM_CONDITIONAL(ENABLE_SELF_CHECKS, test "$enable_self_checks" = "yes")
index 62deb9b6dfdc66ac066f1ccbd1f93ab15a3ce159..f851f4af28690896261eef1e3c498d2c59699910 100644 (file)
@@ -132,6 +132,10 @@ if NEEDS_LIBRT
 thirdparty_libadd += $(LTLIBRT)
 endif
 
+if ENABLE_FIPS140
+thirdparty_libadd += $(FIPS140_LIBS)
+endif
+
 if ENABLE_OPENPGP
 libgnutls_la_LIBADD += openpgp/libgnutls_openpgp.la
 libgnutls_la_LIBADD += opencdk/libminiopencdk.la
index c88ca419f111732d9a265b23598b4fc791c5d0ca..fa6543d2a74a3264b757ed94d634a1310409662c 100644 (file)
 #include <unistd.h>
 #include <gnutls_errors.h>
 #include <fips.h>
+#include <gnutls/fips140.h>
+#include <dlfcn.h>
+
+#define FIPS140_TEST
 
 #ifdef ENABLE_FIPS140
 
@@ -38,14 +42,18 @@ unsigned _gnutls_fips_mode_enabled(void)
            access("/etc/system-fips", R_OK) == 0)
                return 1;
 
+#ifndef FIPS140_TEST
        return 0;
+#else
+       return 1;
+#endif
 }
 
-#ifdef HAVE_DLADDR
 static const char fips_key[] = "I'd rather be skiing.";
 
 #define HMAC_SUFFIX ".hmac"
-
+#define HMAC_SIZE 32
+#define HMAC_ALGO GNUTLS_MAC_SHA256
 
 /* Run an HMAC using the key above on the library binary data. 
  * Returns true success and false on error.
@@ -56,23 +64,24 @@ static unsigned check_binary_integrity(void)
        Dl_info info;
        unsigned prev;
        char mac_file[GNUTLS_PATH_MAX];
-       uint8_t sha256_hmac[32];
-       uint8_t new_sha256_hmac[32];
-       size_t sha256_hmac_size;
+       uint8_t hmac[HMAC_SIZE];
+       uint8_t new_hmac[HMAC_SIZE];
+       size_t hmac_size;
        gnutls_datum_t data;
 
        ret = dladdr("gnutls_global_init", &info);
        if (ret == 0)
                return gnutls_assert_val(0);
 
+       _gnutls_debug_log("Loading: %s\n", info.dli_fname);
        ret = gnutls_load_file(info.dli_fname, &data);
        if (ret < 0)
                return gnutls_assert_val(0);
 
        prev = _gnutls_get_fips_state();
        _gnutls_switch_fips_state(FIPS_STATE_OPERATIONAL);
-       ret = gnutls_hmac_fast(GNUTLS_MAC_SHA256, fips_key, sizeof(fips_key)-1,
-               data.data, data.size, new_sha256_hmac);
+       ret = gnutls_hmac_fast(HMAC_ALGO, fips_key, sizeof(fips_key)-1,
+               data.data, data.size, new_hmac);
        _gnutls_switch_fips_state(prev);
        
        gnutls_free(data.data);
@@ -83,31 +92,26 @@ static unsigned check_binary_integrity(void)
        /* now open the .hmac file and compare */
        snprintf(mac_file, sizeof(mac_file), "%s"HMAC_SUFFIX, info.dli_fname);
        
-       ret = gnutls_load_file(info.dli_fname, &data);
+       ret = gnutls_load_file(mac_file, &data);
        if (ret < 0)
                return gnutls_assert_val(0);
 
-       sha256_hmac_size = sizeof(sha256_hmac);
-       ret = _gnutls_hex2bin(data.data, data.size, sha256_hmac, &sha256_hmac_size);
+       hmac_size = sizeof(hmac);
+       ret = _gnutls_hex2bin((void*)data.data, data.size, hmac, &hmac_size);
        gnutls_free(data.data);
 
        if (ret < 0)
                return gnutls_assert_val(0);
 
-       if (sha256_hmac_size != sizeof(sha256_hmac) ||
-                       memcmp(sha256_hmac, new_sha256_hmac, sizeof(sha256_hmac)) != 0)
+       if (hmac_size != sizeof(hmac) ||
+                       memcmp(hmac, new_hmac, sizeof(hmac)) != 0) {
+               _gnutls_debug_log("Calculated MAC does not match\n");
                return gnutls_assert_val(0);
+       }
        
        return 1;
 }
 
-#else
-static int check_binary_integrity(void)
-{
-       return 1;
-}
-#endif
-
 int _gnutls_fips_perform_self_checks(void)
 {
        int ret;
@@ -210,16 +214,43 @@ int _gnutls_fips_perform_self_checks(void)
        }
        
        ret = check_binary_integrity();
-       if (ret < 0) {
+       if (ret == 0) {
                gnutls_assert();
+#ifndef FIPS140_TEST
                goto error;
+#endif
        }
 
        return 0;
 error:
        _gnutls_switch_fips_state(FIPS_STATE_ERROR);
 
-       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+       return GNUTLS_E_SELF_TEST_ERROR;
 }
+#endif
 
+/**
+ * gnutls_fips140_mode_enabled:
+ *
+ * Checks whether this library is in FIPS140 mode.
+ *
+ * Returns: return non-zero if true or zero if false.
+ *
+ * Since: 3.3.0
+ **/
+int gnutls_fips140_mode_enabled(void)
+{
+#ifdef ENABLE_FIPS140
+
+       return _gnutls_fips_mode_enabled();
+#else
+       return 0;
 #endif
+}
+
+void _gnutls_fips140_simulate_error(void)
+{
+#ifdef ENABLE_FIPS140
+       _gnutls_switch_fips_state(FIPS_STATE_ERROR);
+#endif
+}
index 355ab9ee61ecf81fb02cf4e363653fb11edc0590..25b3e3c7a467fa5d32a20c3e15d72727e67665a1 100644 (file)
@@ -55,10 +55,13 @@ 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
+       if (_gnutls_get_fips_state() != FIPS_STATE_OPERATIONAL && \
+         _gnutls_get_fips_state() != FIPS_STATE_SELFTEST) return GNUTLS_E_LIB_IN_ERROR_STATE
 
 void _gnutls_switch_fips_state(gnutls_fips_state_t state);
 
+void _gnutls_fips140_simulate_error(void);
+
 #else
 
 # define _gnutls_switch_fips_state(x) 0
index 2fb86094c6ead6aa93cefb6f2d54874694275664..2fe1ce2ef069ce39d53d784d9e877d602d081f56 100644 (file)
@@ -23,6 +23,10 @@ nobase_include_HEADERS = gnutls/x509.h gnutls/pkcs12.h gnutls/compat.h       \
        gnutls/abstract.h gnutls/dtls.h gnutls/ocsp.h gnutls/tpm.h      \
        gnutls/xssl.h
 
+if ENABLE_FIPS140
+nobase_include_HEADERS += gnutls/fips140.h
+endif
+
 if ENABLE_CXX
 nobase_include_HEADERS += gnutls/gnutlsxx.h
 endif
diff --git a/lib/includes/gnutls/fips140.h b/lib/includes/gnutls/fips140.h
new file mode 100644 (file)
index 0000000..f60c814
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- c -*-
+ * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ *
+ * 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/>
+ *
+ */
+
+/* This file contains the types and prototypes for all the
+ * high level functionality of the gnutls main library.
+ *
+ * If the optional C++ binding was built, it is available in
+ * gnutls/gnutlsxx.h.
+ *
+ * The openssl compatibility layer (which is under the GNU GPL
+ * license) is in gnutls/openssl.h.
+ *
+ * The low level cipher functionality is in gnutls/crypto.h.
+ */
+
+
+#ifndef GNUTLS_FIPS140_H
+#define GNUTLS_FIPS140_H
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* *INDENT-ON* */
+
+
+int gnutls_fips140_mode_enabled(void);
+
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+}
+#endif
+/* *INDENT-ON* */
+
+#endif
index b3fea6e3892d74a155a3aad86b455ae9c0614a88..57899b79c1d5da2d70fe3fba4436a753029f516d 100644 (file)
@@ -932,6 +932,8 @@ GNUTLS_3_1_0 {
        gnutls_mac_self_test;
        gnutls_digest_self_test;
        gnutls_privkey_generate;
+
+       gnutls_fips140_mode_enabled;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
@@ -963,6 +965,9 @@ GNUTLS_PRIVATE {
     _gnutls_buffer_init;
     _gnutls_buffer_append_str;
     _gnutls_buffer_to_datum;
+
+    # Internal symbols used by fips-test
+    _gnutls_fips140_simulate_error;
     # Internal symbols needed by psktool:
 
     # Internal symbols needed by gnutls-cli-debug:
index 11780ee85f6c0706d0e89848eca90a59065325c7..237c6860d713ec4eb8fe8319d2cbdee41b8ee8cf 100644 (file)
@@ -303,8 +303,6 @@ 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)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
@@ -351,8 +349,6 @@ int xssl_client_init(xssl_t * isb, const char *hostname,
        int ret;
        unsigned len;
        
-       FAIL_IF_FIPS_ERROR;
-
        ret = gnutls_init(&session, GNUTLS_CLIENT);
        if (ret < 0)
                return gnutls_assert_val(ret);
index ae0a45bd881c037398f4772eead0cf1c1ec9738b..4929de2048f792fe7b0f241d26c443da24d92620 100644 (file)
@@ -75,6 +75,10 @@ ctests = simple gc set_pkcs12_cred certder certuniqueid      \
         mini-record mini-dtls-record mini-handshake-timeout mini-record-range \
         mini-cert-status mini-rsa-psk mini-record-2
 
+if ENABLE_FIPS140
+ctests += fips-test
+endif
+
 if ENABLE_OCSP
 ctests += ocsp
 endif
diff --git a/tests/fips-test.c b/tests/fips-test.c
new file mode 100644 (file)
index 0000000..cbe3dbb
--- /dev/null
@@ -0,0 +1,142 @@
+#include <config.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils.h>
+#include <stdlib.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <gnutls/abstract.h>
+#include <gnutls/x509.h>
+#include <gnutls/fips140.h>
+
+void _gnutls_fips140_simulate_error(void);
+
+/* This does check the FIPS140 support.
+ */
+
+static void tls_log_func(int level, const char *str)
+{
+       fprintf(stderr, "<%d>| %s", level, str);
+}
+
+static char key16[16];
+static char iv16[16];
+
+void doit(void)
+{
+int ret;
+#ifdef ENABLE_FIPS140
+       gnutls_cipher_hd_t ch;
+       gnutls_hmac_hd_t mh;
+       gnutls_session_t session;
+       gnutls_pubkey_t pubkey;
+       gnutls_x509_privkey_t xprivkey;
+       gnutls_privkey_t privkey;
+       gnutls_datum_t key = { key16, sizeof(key16) };
+       gnutls_datum_t iv = { iv16, sizeof(iv16) };
+
+       fprintf(stderr, "Please note that you need to assure the library's integrity prior to running this test\n");
+
+       gnutls_global_set_log_function(tls_log_func);
+       if (debug)
+               gnutls_global_set_log_level(4711);
+
+       ret = gnutls_fips140_mode_enabled();
+       if (ret == 0) {
+               fail("We are not in FIPS140 mode\n");
+       }
+
+       ret = global_init();
+       if (ret < 0) {
+               fail("Cannot initialize library\n");
+       }
+       
+       /* Try crypto.h functionality */
+       ret = gnutls_cipher_init(&ch, GNUTLS_CIPHER_AES_128_CBC, &key, &iv);
+       if (ret < 0) {
+               fail("gnutls_cipher_init failed\n");
+       }
+       gnutls_cipher_deinit(ch);
+
+       ret = gnutls_hmac_init(&mh, GNUTLS_MAC_SHA1, key.data, key.size);
+       if (ret < 0) {
+               fail("gnutls_hmac_init failed\n");
+       }
+       gnutls_hmac_deinit(mh, NULL);
+
+       ret = gnutls_rnd(GNUTLS_RND_NONCE, key16, sizeof(key16));
+       if (ret < 0) {
+               fail("gnutls_rnd failed\n");
+       }
+
+       ret = gnutls_pubkey_init(&pubkey);
+       if (ret < 0) {
+               fail("gnutls_pubkey_init failed\n");
+       }
+       gnutls_pubkey_deinit(pubkey);
+
+       ret = gnutls_privkey_init(&privkey);
+       if (ret < 0) {
+               fail("gnutls_privkey_init failed\n");
+       }
+       gnutls_privkey_deinit(privkey);
+
+       ret = gnutls_x509_privkey_init(&xprivkey);
+       if (ret < 0) {
+               fail("gnutls_privkey_init failed\n");
+       }
+       gnutls_x509_privkey_deinit(xprivkey);
+       
+       ret = gnutls_init(&session, 0);
+       if (ret < 0) {
+               fail("gnutls_init failed\n");
+       }
+       gnutls_deinit(session);
+
+       /* Test when FIPS140 is set to error state */
+       _gnutls_fips140_simulate_error();
+       
+       
+       /* Try crypto.h functionality */
+       ret = gnutls_cipher_init(&ch, GNUTLS_CIPHER_AES_128_CBC, &key, &iv);
+       if (ret >= 0) {
+               fail("gnutls_cipher_init succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_hmac_init(&mh, GNUTLS_MAC_SHA1, key.data, key.size);
+       if (ret >= 0) {
+               fail("gnutls_hmac_init succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_rnd(GNUTLS_RND_NONCE, key16, sizeof(key16));
+       if (ret >= 0) {
+               fail("gnutls_rnd succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_pubkey_init(&pubkey);
+       if (ret >= 0) {
+               fail("gnutls_pubkey_init succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_privkey_init(&privkey);
+       if (ret >= 0) {
+               fail("gnutls_privkey_init succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_x509_privkey_init(&xprivkey);
+       if (ret >= 0) {
+               fail("gnutls_x509_privkey_init succeeded when in FIPS140 error state\n");
+       }
+
+       ret = gnutls_init(&session, 0);
+       if (ret >= 0) {
+               fail("gnutls_init succeeded when in FIPS140 error state\n");
+       }
+       
+       gnutls_global_deinit();
+       return 0;
+#else
+       return 1; /* fail. This script shouldn't be called on this case */
+#endif
+}