Experimental multi-implementation support for FIPS capable OpenSSL.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 13 May 2012 18:40:12 +0000 (18:40 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 13 May 2012 18:40:12 +0000 (18:40 +0000)
When in FIPS mode the approved implementations are used as normal,
when not in FIPS mode the internal unapproved versions are used instead.
This means that the FIPS capable OpenSSL isn't forced to use the
(often lower perfomance) FIPS implementations outside FIPS mode.

13 files changed:
CHANGES
crypto/evp/Makefile
crypto/evp/digest.c
crypto/evp/e_aes.c
crypto/evp/e_des3.c
crypto/evp/e_null.c
crypto/evp/evp_enc.c
crypto/evp/m_dss.c
crypto/evp/m_dss1.c
crypto/evp/m_ecdsa.c
crypto/evp/m_sha1.c
crypto/hmac/hmac.c
crypto/rsa/rsa_pmeth.c

diff --git a/CHANGES b/CHANGES
index fb0bf2cba088da635ab7ba1fdc6f3684647c2f1c..405c314c4c36da61d3348878ed5874aa3f2e77de 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,13 @@
 
  Changes between 1.0.1 and 1.0.2 [xx XXX xxxx]
 
+  *) Experimental multi-implementation support for FIPS capable OpenSSL.
+     When in FIPS mode the approved implementations are used as normal,
+     when not in FIPS mode the internal unapproved versions are used instead.
+     This means that the FIPS capable OpenSSL isn't forced to use the
+     (often lower perfomance) FIPS implementations outside FIPS mode.
+     [Steve Henson]
+
   *) Transparently support X9.42 DH parameters when calling
      PEM_read_bio_DHparameters. This means existing applications can handle
      the new parameter format automatically.
index 9c79f66f560598bbf47e1baf8319ed8a91cd456b..229536ef53f9a77ba822db4eb7f687d58581ae6d 100644 (file)
@@ -28,7 +28,7 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c \
        bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
        c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
        evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c \
-       e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c evp_fips.c \
+       e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
        e_aes_cbc_hmac_sha1.c e_rc4_hmac_md5.c
 
 LIBOBJ=        encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \
@@ -41,7 +41,7 @@ LIBOBJ=       encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \
        bio_md.o bio_b64.o bio_enc.o evp_err.o e_null.o \
        c_all.o c_allc.o c_alld.o evp_lib.o bio_ok.o \
        evp_pkey.o evp_pbe.o p5_crpt.o p5_crpt2.o \
-       e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o evp_fips.o \
+       e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o \
        e_aes_cbc_hmac_sha1.o e_rc4_hmac_md5.o
 
 SRC= $(LIBSRC)
index 467e6b5ae9cf930775fd8e21c192294a5f2cfab7..feab0831be0d49940dd01e65fb7b1fda16780fd6 100644 (file)
@@ -145,6 +145,19 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
 int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
        {
        EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
+#ifdef OPENSSL_FIPS_
+       /* If FIPS mode switch to approved implementation if possible */
+       if (FIPS_mode())
+               {
+               const EVP_MD *fipsmd;
+               if (type)
+                       {
+                       fipsmd = FIPS_get_digestbynid(EVP_MD_type(type));
+                       if (fipsmd)
+                               type = fipsmd;
+                       }
+               }
+#endif
 #ifndef OPENSSL_NO_ENGINE
        /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
         * so this context may already have an ENGINE! Try to avoid releasing
index 1e4af0cb7511e598b9d371e669722769e2b275ef..a0c27ef1392fa74cc8dcb95fbfbb61d706e99611 100644 (file)
 #include <assert.h>
 #include <openssl/aes.h>
 #include "evp_locl.h"
-#ifndef OPENSSL_FIPS
 #include "modes_lcl.h"
 #include <openssl/rand.h>
 
+#ifndef OPENSSL_FIPSCANISTER
+#undef EVP_CIPH_FLAG_FIPS
+#define EVP_CIPH_FLAG_FIPS 0
+#endif
+
 typedef struct
        {
        AES_KEY ks;
@@ -715,7 +719,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
        case EVP_CTRL_GCM_SET_IVLEN:
                if (arg <= 0)
                        return 0;
-#ifdef OPENSSL_FIPS
+#ifdef OPENSSL_FIPSCANISTER
                if (FIPS_module_mode() && !(c->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)
                                                 && arg < 12)
                        return 0;
@@ -1126,7 +1130,7 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                return 0;
        if (!out || !in || len<AES_BLOCK_SIZE)
                return 0;
-#ifdef OPENSSL_FIPS
+#ifdef OPENSSL_FIPSCANISTER
        /* Requirement of SP800-38E */
        if (FIPS_module_mode() && !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW) &&
                        (len > (1UL<<20)*16))
@@ -1310,4 +1314,3 @@ BLOCK_CIPHER_custom(NID_aes,192,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
 BLOCK_CIPHER_custom(NID_aes,256,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
 
 #endif
-#endif
index 1e699726627d2bf017af73e02b537fd82fafa70e..3232cfe024b2b3d671c431537bf669fe78cf4c17 100644 (file)
@@ -65,8 +65,6 @@
 #include <openssl/des.h>
 #include <openssl/rand.h>
 
-#ifndef OPENSSL_FIPS
-
 static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                            const unsigned char *iv,int enc);
 
@@ -313,4 +311,3 @@ const EVP_CIPHER *EVP_des_ede3(void)
        return &des_ede3_ecb;
 }
 #endif
-#endif
index f0c1f78b5fec941308d5528d6f56c751af7c61c5..98a78499f9671b9065c7b3db453f16314e49f9b1 100644 (file)
@@ -61,8 +61,6 @@
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 
-#ifndef OPENSSL_FIPS
-
 static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
        const unsigned char *iv,int enc);
 static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
@@ -101,4 +99,3 @@ static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                memcpy((char *)out,(const char *)in,inl);
        return 1;
        }
-#endif
index 0c54f05e6ef511e3ae27ed0ec2b46c1ea26fa9f1..6da323077a2ac01bd7d325e9ccc223bff77426ee 100644 (file)
@@ -171,7 +171,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *imp
 
 #ifdef OPENSSL_FIPS
                if (FIPS_mode())
+                       {
+                       const EVP_CIPHER *fcipher;
+                       if (cipher)
+                               fcipher = FIPS_get_cipherbynid(EVP_CIPHER_type(cipher));
+                       if (fcipher)
+                               cipher = fcipher;
                        return FIPS_cipherinit(ctx, cipher, key, iv, enc);
+                       }
 #endif
                ctx->cipher=cipher;
                if (ctx->cipher->ctx_size)
index 4ad63ada6fe228c859eccbac137c63f5c3d1d218..48c2689504821fdeeaef5f3f0b06118eab40725e 100644 (file)
@@ -66,7 +66,6 @@
 #endif
 
 #ifndef OPENSSL_NO_SHA
-#ifndef OPENSSL_FIPS
 
 static int init(EVP_MD_CTX *ctx)
        { return SHA1_Init(ctx->md_data); }
@@ -98,4 +97,3 @@ const EVP_MD *EVP_dss(void)
        return(&dsa_md);
        }
 #endif
-#endif
index f80170efeb98404e446ac24ac5ffbd1ce5e08267..4f03fb70e0263e84566c24d333ddd06b7cee71ce 100644 (file)
@@ -68,8 +68,6 @@
 #include <openssl/dsa.h>
 #endif
 
-#ifndef OPENSSL_FIPS 
-
 static int init(EVP_MD_CTX *ctx)
        { return SHA1_Init(ctx->md_data); }
 
@@ -100,4 +98,3 @@ const EVP_MD *EVP_dss1(void)
        return(&dss1_md);
        }
 #endif
-#endif
index 4b15fb0f6cec0bc3c84ea623cdacd34649a1a382..a6ed24b0b68f69b557bb511a5fd393c70c5ca4a8 100644 (file)
 #include <openssl/x509.h>
 
 #ifndef OPENSSL_NO_SHA
-#ifndef OPENSSL_FIPS
 
 static int init(EVP_MD_CTX *ctx)
        { return SHA1_Init(ctx->md_data); }
@@ -148,4 +147,3 @@ const EVP_MD *EVP_ecdsa(void)
        return(&ecdsa_md);
        }
 #endif
-#endif
index 3cb11f1ebb1f3ca28cd21821f5f7612be416ee5b..9492a544d979dda64a94f5c14fb785f9ee73e7c6 100644 (file)
@@ -59,8 +59,6 @@
 #include <stdio.h>
 #include "cryptlib.h"
 
-#ifndef OPENSSL_FIPS
-
 #ifndef OPENSSL_NO_SHA
 
 #include <openssl/evp.h>
@@ -206,4 +204,3 @@ const EVP_MD *EVP_sha512(void)
        { return(&sha512_md); }
 #endif /* ifndef OPENSSL_NO_SHA512 */
 
-#endif
index ba27cbf56f2e9f843627795da68240240b67f5d9..45335a1f7af3344d7de54f4a65221334d78ba92a 100644 (file)
@@ -72,6 +72,18 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
        unsigned char pad[HMAC_MAX_MD_CBLOCK];
 
 #ifdef OPENSSL_FIPS
+       /* If FIPS mode switch to approved implementation if possible */
+       if (FIPS_mode())
+               {
+               const EVP_MD *fipsmd;
+               if (md)
+                       {
+                       fipsmd = FIPS_get_digestbynid(EVP_MD_type(md));
+                       if (fipsmd)
+                               md = fipsmd;
+                       }
+               }
+
        if (FIPS_mode())
                {
                /* If we have an ENGINE need to allow non FIPS */
index 5b2ecf56adc7343b8661ac4c9c4222a00dde5a10..b654b00ea865586ec3db98f69ea4551888f7dea7 100644 (file)
@@ -174,10 +174,20 @@ static int pkey_fips_check_ctx(EVP_PKEY_CTX *ctx)
                rv = 0;
        if (!(rsa->meth->flags & RSA_FLAG_FIPS_METHOD) && rv)
                return -1;
-       if (rctx->md && !(rctx->md->flags & EVP_MD_FLAG_FIPS))
-               return rv;
+       if (rctx->md)
+               {
+               const EVP_MD *fmd;
+               fmd = FIPS_get_digestbynid(EVP_MD_type(rctx->md));
+               if (!fmd || !(fmd->flags & EVP_MD_FLAG_FIPS))
+                       return rv;
+               }
        if (rctx->mgf1md && !(rctx->mgf1md->flags & EVP_MD_FLAG_FIPS))
-               return rv;
+               {
+               const EVP_MD *fmd;
+               fmd = FIPS_get_digestbynid(EVP_MD_type(rctx->mgf1md));
+               if (!fmd || !(fmd->flags & EVP_MD_FLAG_FIPS))
+                       return rv;
+               }
        return 1;
        }
 #endif