]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
First cut, working FIPS mode.
authorBen Laurie <ben@apache.org>
Fri, 10 Jun 2005 17:25:17 +0000 (17:25 +0000)
committerBen Laurie <ben@apache.org>
Fri, 10 Jun 2005 17:25:17 +0000 (17:25 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/fips-dev@189992 13f79535-47bb-0310-9956-ffa450edef68

README-FIPS
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_config.c
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_rand.c
modules/ssl/ssl_private.h
server/config.c
server/main.c

index 6935eac75a7571832a4aa644a59f7e8ff1da651d..26f36dc2bf0186617661ca86528de5b3be2ff1f0 100644 (file)
@@ -22,3 +22,13 @@ build of the OpenSSL library.
 Note this branch includes apr and apr-util, while the authors figure out what\r
 to do about apr MD5 and other fips issues are resolved.  That work will be\r
 submitted to the apr project, once the least distruptive change is ascertained.\r
+\r
+Stuff FIPS requires\r
+-------------------\r
+\r
+Random number seeding: strangeness about the FIPS PRNG means that at\r
+least one random source must supply at least 24 bytes of randomness in\r
+a single chunk (note that this could be relaxed at the cost of more\r
+code).\r
+\r
+Certificates: must be signed using SHA-1.\r
index 146f7e7a66a544da6774f37c8317a690e093d7db..f973a611f9f63d6e4f188ec32d31a138131144a5 100644 (file)
@@ -99,6 +99,9 @@ static const command_rec ssl_config_cmds[] = {
     SSL_CMD_SRV(Engine, TAKE1,
                 "SSL switch for the protocol engine "
                 "(`on', `off')")
+    SSL_CMD_SRV(FIPS, TAKE1,
+               "Enable FIPS-140 compliance "
+                "(`on', `off')")
     SSL_CMD_ALL(CipherSuite, TAKE1,
                 "Colon-delimited list of permitted SSL Ciphers "
                 "(`XXX:...:XXX' - see manual)")
index c6572216e2cc700e6b5ffdaaca5b5be00684404c..16d13024a994586ad5dbf9bc7659830fa1f4d163 100644 (file)
@@ -254,6 +254,7 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
 
     cfgMerge(mc, NULL);
     cfgMerge(enabled, SSL_ENABLED_UNSET);
+    cfgMerge(fips, SSL_FIPS_UNSET); // FIPS-XXX: make more than one setting an error?
     cfgMergeBool(proxy_enabled);
     cfgMergeInt(session_cache_timeout);
     cfgMergeBool(cipher_server_pref);
@@ -618,6 +619,22 @@ const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
 
     return "Argument must be On, Off, or Optional";
 }
+// FIPS-XXX: this is global, i.e. can only be set once, not per-server.
+const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, const char *arg)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    if (!strcasecmp(arg, "On")) {
+        sc->fips = SSL_FIPS_TRUE;
+       return NULL;
+    }
+    else if (!strcasecmp(arg, "Off")) {
+        sc->fips = SSL_FIPS_FALSE;
+        return NULL;
+    }
+
+    return "Argument must be On or Off";
+}
 
 const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
                                    void *dcfg,
index 90094df44fbc287507b89730585507a020135d58..01b336f2e5224414dc1b227b2f9e9f65756bd5e4 100644 (file)
@@ -87,6 +87,20 @@ static void ssl_add_version_components(apr_pool_t *p,
     MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_512); \
     MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_1024)
 
+/* FIPS-140 prevents automatic rekeying in child processes, so we have
+ * to do it */
+
+static void fips_rand_reseed(server_rec *s, apr_pool_t *ptemp)
+{
+    static int rand_seeded;
+    SSLSrvConfigRec *sc = mySrvConfig(s);
+
+    if(sc->fips == SSL_FIPS_TRUE && !rand_seeded) {
+       ssl_rand_seed(s, ptemp, SSL_RSCTX_STARTUP, "FIPS Child Init: ");
+       rand_seeded=1;
+    }
+}
+
 static void ssl_tmp_keys_free(server_rec *s)
 {
     SSLModConfigRec *mc = myModConfig(s);
@@ -95,8 +109,7 @@ static void ssl_tmp_keys_free(server_rec *s)
     MODSSL_TMP_KEYS_FREE(mc, DH);
 }
 
-static int ssl_tmp_key_init_rsa(server_rec *s,
-                                int bits, int idx)
+static int ssl_tmp_key_init_rsa(server_rec *s, int bits, int idx)
 {
     SSLModConfigRec *mc = myModConfig(s);
 
@@ -106,6 +119,7 @@ static int ssl_tmp_key_init_rsa(server_rec *s,
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                      "Init: Failed to generate temporary "
                      "%d bit RSA private key", bits);
+       ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
         return !OK;
     }
 
@@ -157,8 +171,7 @@ static int ssl_tmp_keys_init(server_rec *s)
 }
 
 /*
- *  Per-module initialization
- */
+ * Per-module initialization */
 int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
                     apr_pool_t *ptemp,
                     server_rec *base_server)
@@ -166,6 +179,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
     SSLModConfigRec *mc = myModConfig(base_server);
     SSLSrvConfigRec *sc;
     server_rec *s;
+    static int fips_done;
 
     /* We initialize mc->pid per-process in the child init,
      * but it should be initialized for startup before we
@@ -212,6 +226,10 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
         if (sc->enabled == SSL_ENABLED_UNSET) {
             sc->enabled = SSL_ENABLED_FALSE;
         }
+
+       if(sc->fips == SSL_FIPS_UNSET)
+           sc->enabled = SSL_FIPS_FALSE;
+
         if (sc->proxy_enabled == UNSET) {
             sc->proxy_enabled = FALSE;
         }
@@ -247,6 +265,25 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
      */
     ssl_rand_seed(base_server, ptemp, SSL_RSCTX_STARTUP, "Init: ");
 
+    /* Do this after randomness has been seeded */
+    // XXX: also need to set FIPS mode for APR (i.e. exclude all crypto/randomness from APR)
+    if(!fips_done) {
+       if(sc->fips == SSL_FIPS_TRUE) {
+           if(FIPS_mode_set(1,ap_server_full_argv0))
+               ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,
+                            "FIPS mode enabled");
+           else {
+               ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
+                            "FIPS mode failed (%s)",ap_server_full_argv0);
+               ssl_log_ssl_error(APLOG_MARK, APLOG_EMERG, s);
+               exit(1);
+           }
+       }
+       else
+           ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, "FIPS mode disabled");
+       fips_done=1;
+    }
+
     /*
      * read server private keys/public certs into memory.
      * decrypting any encrypted keys via configured SSLPassPhraseDialogs
@@ -1185,6 +1222,7 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s,
 void ssl_init_Child(apr_pool_t *p, server_rec *s)
 {
     SSLModConfigRec *mc = myModConfig(s);
+
     mc->pid = getpid(); /* only call getpid() once per-process */
 
     /* XXX: there should be an ap_srand() function */
@@ -1192,6 +1230,8 @@ void ssl_init_Child(apr_pool_t *p, server_rec *s)
 
     /* open the mutex lockfile */
     ssl_mutex_reinit(s, p);
+
+    fips_rand_reseed(s, p);
 }
 
 #define MODSSL_CFG_ITEM_FREE(func, item) \
index 486759c702887daa10849223f8909b015dd09b09..b8c92dda77f6c9c5f0c772252ee1d6ed6a04cab3 100644 (file)
 */
 
 static int ssl_rand_choosenum(int, int);
-static int ssl_rand_feedfp(apr_pool_t *, apr_file_t *, int);
+static int ssl_rand_feedfp(int, apr_pool_t *, apr_file_t *, int);
+
+/* Deal with the arcanity of the FIPS PRNG, which requires keying
+ * indepently of seeding. */
+// FIPS-XXX: this means at least one random source _must_ inject 24 bytes or
+// FIPS will not be seeded and keyed
+static void inject_rand(int fips, const void *buf, int num)
+{
+    if(!fips)
+       RAND_seed(buf, num);
+
+    if(num > 16) {
+       FIPS_set_prng_key(buf, buf+8);
+       num -= 16;
+       buf += 16;
+    }
+    RAND_seed(buf, num);
+}
 
 int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
 {
     SSLModConfigRec *mc;
+    SSLSrvConfigRec *sc = mySrvConfig(s);
     apr_array_header_t *apRandSeed;
     ssl_randseed_t *pRandSeeds;
     ssl_randseed_t *pRandSeed;
@@ -65,7 +83,8 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
                 if (apr_file_open(&fp, pRandSeed->cpPath, 
                                   APR_READ, APR_OS_DEFAULT, p) != APR_SUCCESS)
                     continue;
-                nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes);
+                nDone += ssl_rand_feedfp(sc->fips == SSL_FIPS_TRUE, p, fp,
+                                        pRandSeed->nBytes);
                 apr_file_close(fp);
             }
             else if (pRandSeed->nSrc == SSL_RSSRC_EXEC) {
@@ -80,7 +99,8 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
 
                 if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
                     continue;
-                nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes);
+                nDone += ssl_rand_feedfp(sc->fips == SSL_FIPS_TRUE, p, fp,
+                                        pRandSeed->nBytes);
                 ssl_util_ppclose(s, p, fp);
             }
 #ifdef HAVE_SSL_RAND_EGD
@@ -111,14 +131,14 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
                 my_seed.pid = mc->pid;
 
                 l = sizeof(my_seed);
-                RAND_seed((unsigned char *)&my_seed, l);
+                inject_rand(sc->fips == SSL_FIPS_TRUE, &my_seed, l);
                 nDone += l;
                 
                 /*
                  * seed in some current state of the run-time stack (128 bytes)
                  */
                 n = ssl_rand_choosenum(0, sizeof(stackdata)-128-1);
-                RAND_seed(stackdata+n, 128);
+                inject_rand(sc->fips == SSL_FIPS_TRUE, stackdata+n, 128);
                 nDone += 128;
 
             }
@@ -136,7 +156,7 @@ int ssl_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
 
 #define BUFSIZE 8192
 
-static int ssl_rand_feedfp(apr_pool_t *p, apr_file_t *fp, int nReq)
+static int ssl_rand_feedfp(int fips, apr_pool_t *p, apr_file_t *fp, int nReq)
 {
     apr_size_t nDone;
     unsigned char caBuf[BUFSIZE];
@@ -153,7 +173,7 @@ static int ssl_rand_feedfp(apr_pool_t *p, apr_file_t *fp, int nReq)
         nBuf = nRead;
         if (apr_file_read(fp, caBuf, &nBuf) != APR_SUCCESS)
             break;
-        RAND_seed(caBuf, nBuf);
+        inject_rand(fips, caBuf, nBuf);
         nDone += nBuf;
         if (nReq > 0) {
             nTodo -= nBuf;
index 71db2d1fd5eff73b0a7c7c2deb4aa721f62c95f0..260c348f0a98600558daecb5f7e75d9b76fce8f8 100644 (file)
@@ -278,9 +278,15 @@ typedef enum {
     SSL_ENABLED_UNSET    = UNSET,
     SSL_ENABLED_FALSE    = 0,
     SSL_ENABLED_TRUE     = 1,
-       SSL_ENABLED_OPTIONAL = 3
+    SSL_ENABLED_OPTIONAL = 3
 } ssl_enabled_t;
 
+typedef enum {
+    SSL_FIPS_UNSET     = UNSET,
+    SSL_FIPS_FALSE     = 0,
+    SSL_FIPS_TRUE      = 1
+} fips_enabled_t;
+
 /*
  * Define the SSL requirement structure
  */
@@ -436,6 +442,7 @@ typedef struct {
 struct SSLSrvConfigRec {
     SSLModConfigRec *mc;
     ssl_enabled_t    enabled;
+    fips_enabled_t   fips;
     BOOL             proxy_enabled;
     const char      *vhost_id;
     int              vhost_id_len;
@@ -487,6 +494,7 @@ const char  *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
 const char  *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *);
+const char  *ssl_cmd_SSLFIPS(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
index e44674f9bf6395fb05b55658eb8c8695418a6eda..6aac9c594232e8cbca39438de3156a9424e0ea5c 100644 (file)
@@ -55,6 +55,7 @@
 
 
 AP_DECLARE_DATA const char *ap_server_argv0 = NULL;
+AP_DECLARE_DATA const char *ap_server_full_argv0 = NULL;
 
 AP_DECLARE_DATA const char *ap_server_root = NULL;
 
index 732b10097b61016b1abaeb2a6054404ceaebc883..491d21137d5a18281b12c2649d71d1bab7eb45c6 100644 (file)
@@ -429,6 +429,7 @@ int main(int argc, const char * const argv[])
 
     AP_MONCONTROL(0); /* turn off profiling of startup */
 
+    ap_server_full_argv0 = argv[0];
     apr_app_initialize(&argc, &argv, NULL);
 
     process = create_process(argc, argv);