From 49db15dbdee366c63f5bbb1eba09d9d91e11b97d Mon Sep 17 00:00:00 2001
From: Ludwig Nussel <ludwig.nussel@suse.de>
Date: Wed, 24 Sep 2014 17:58:59 +0200
Subject: [PATCH 2/6] disable algorithms that are not allowed in fips

---
 cipher/cipher.c | 11 ++++++++++
 cipher/mac.c    | 17 +++++++++++++++
 cipher/md.c     | 11 ++++++++++
 cipher/md5.c    |  7 +++++-
 cipher/pubkey.c | 11 ++++++++++
 src/g10lib.h    |  1 +
 src/global.c    |  3 +++
 tests/basic.c   | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 8 files changed, 120 insertions(+), 8 deletions(-)

diff --git a/cipher/cipher.c b/cipher/cipher.c
index 8c5a0b4..f0a7973 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1364,6 +1364,17 @@ _gcry_cipher_get_algo_blklen (int algo)
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_cipher_spec_t *spec;
+
+      for (idx = 0; (spec = cipher_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
   return 0;
 }
 
diff --git a/cipher/mac.c b/cipher/mac.c
index fa36c7d..b9527de 100644
--- a/cipher/mac.c
+++ b/cipher/mac.c
@@ -104,6 +104,23 @@ static gcry_mac_spec_t *mac_list[] = {
   NULL,
 };
 
+/* Explicitly initialize this module.  */
+gcry_err_code_t
+_gcry_mac_init (void)
+{
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_mac_spec_t *spec;
+
+      for (idx = 0; (spec = mac_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
+  return 0;
+}
 
 
 /* Return the spec structure for the MAC algorithm ALGO.  For an
diff --git a/cipher/md.c b/cipher/md.c
index 22da30a..c737aaa 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -1207,6 +1207,17 @@ _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
 gcry_err_code_t
 _gcry_md_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_md_spec_t *spec;
+
+      for (idx = 0; (spec = digest_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
   return 0;
 }
 
diff --git a/cipher/md5.c b/cipher/md5.c
index b0187c9..081179b 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -59,6 +59,11 @@ md5_init( void *context, unsigned int flags)
 
   (void)flags;
 
+  if (fips_mode()) {
+    /* should never happen but never say never ... */
+    log_fatal("Every time you use MD5 god kills a kitten. How many more have to die?\n");
+  }
+
   ctx->A = 0x67452301;
   ctx->B = 0xefcdab89;
   ctx->C = 0x98badcfe;
@@ -295,7 +300,7 @@ static gcry_md_oid_spec_t oid_spec_md5[] =
 
 gcry_md_spec_t _gcry_digest_spec_md5 =
   {
-    GCRY_MD_MD5, {0, 1},
+    GCRY_MD_MD5, {0, 0},
     "MD5", asn, DIM (asn), oid_spec_md5, 16,
     md5_init, _gcry_md_block_write, md5_final, md5_read,
     sizeof (MD5_CONTEXT)
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index d130388..75779ce 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -929,6 +929,17 @@ _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
 gcry_err_code_t
 _gcry_pk_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_pk_spec_t *spec;
+
+      for (idx = 0; (spec = pubkey_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+ 
   return 0;
 }
 
diff --git a/src/g10lib.h b/src/g10lib.h
index 43dc011..7805e64 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -363,6 +363,7 @@ void __gcry_burn_stack (unsigned int bytes);
 
 gcry_err_code_t _gcry_cipher_init (void);
 gcry_err_code_t _gcry_md_init (void);
+gcry_err_code_t _gcry_mac_init (void);
 gcry_err_code_t _gcry_pk_init (void);
 gcry_err_code_t _gcry_secmem_module_init (void);
 gcry_err_code_t _gcry_mpi_init (void);
diff --git a/src/global.c b/src/global.c
index a25149d..2e5439b 100644
--- a/src/global.c
+++ b/src/global.c
@@ -112,6 +112,9 @@ global_init (void)
   err = _gcry_md_init ();
   if (err)
     goto fail;
+  err = _gcry_mac_init ();
+  if (err)
+    goto fail;
   err = _gcry_pk_init ();
   if (err)
     goto fail;
diff --git a/tests/basic.c b/tests/basic.c
index 86be89d..8657936 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -582,6 +582,14 @@ check_ctr_cipher (void)
       if (!tv[i].algo)
         continue;
 
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
       if (!err)
 	err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
@@ -813,6 +821,14 @@ check_cfb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking CFB mode for %s [%i]\n",
 		 gcry_cipher_algo_name (tv[i].algo),
@@ -984,6 +1000,14 @@ check_ofb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking OFB mode for %s [%i]\n",
 		 gcry_cipher_algo_name (tv[i].algo),
@@ -1286,6 +1310,14 @@ _check_gcm_cipher (unsigned int step)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking GCM mode for %s [%i]\n",
                  gcry_cipher_algo_name (tv[i].algo),
@@ -1961,6 +1993,14 @@ check_ccm_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking CCM mode for %s [%i]\n",
                  gcry_cipher_algo_name (tv[i].algo),
@@ -2521,6 +2561,13 @@ check_stream_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
       if (verbose)
         fprintf (stderr, "    checking stream mode for %s [%i] (%s)\n",
 		 gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
@@ -2965,6 +3012,14 @@ check_stream_cipher_large_block (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking large block stream for %s [%i] (%s)\n",
 		 gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
@@ -3604,11 +3659,11 @@ check_ciphers (void)
 
   for (i = 0; algos2[i]; i++)
     {
-      if (gcry_cipher_test_algo (algos[i]) && in_fips_mode)
+      if (gcry_cipher_test_algo (algos2[i]) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
-		     algos[i]);
+		     algos2[i]);
           continue;
         }
       if (verbose)
@@ -4058,7 +4113,7 @@ check_digests (void)
 
   for (i = 0; algos[i].md; i++)
     {
-      if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
+      if ((gcry_md_test_algo (algos[i].md))
           && in_fips_mode)
         {
           if (verbose)
@@ -4482,8 +4537,7 @@ check_hmac (void)
 
   for (i = 0; algos[i].md; i++)
     {
-      if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
-          && in_fips_mode)
+      if ((gcry_md_test_algo (algos[i].md)) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
@@ -5079,8 +5133,7 @@ check_mac (void)
 
   for (i = 0; algos[i].algo; i++)
     {
-      if ((gcry_mac_test_algo (algos[i].algo)
-	   || algos[i].algo == GCRY_MAC_HMAC_MD5) && in_fips_mode)
+      if (gcry_mac_test_algo (algos[i].algo) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
-- 
2.1.0

