From 862552622978b3d2a86ebaea833ce8c79246439a Mon Sep 17 00:00:00 2001 From: rcritten <> Date: Aug 19 2005 21:42:43 +0000 Subject: Add a FIPS configuration option. This enables the FIPS internal database module, configures for SSLv3 and TLSv1 and enables the 2 FIPS ciphers (and disables all the others). --- diff --git a/docs/mod_nss.html b/docs/mod_nss.html index f91c19a..1d9d5d8 100644 --- a/docs/mod_nss.html +++ b/docs/mod_nss.html @@ -346,6 +346,17 @@ Example

NSSEngine on

+NSSFIPS
+
+Enables or disables FIPS 140 mode. This replaces the standard +internal PKCS#11 module with a FIPS-enabled one. It also forces the enabled protocols to SSLv3 and TLSv1 and disables all ciphers but the FIPS ones.
+
+
FIPS is disabled by default.
+
+Example

+
+NSSFIPS on
+
NSSCipherSuite

A space-separated list of the SSL ciphers used, with the prefix + diff --git a/mod_nss.c b/mod_nss.c index 4a7340f..bf9e84b 100644 --- a/mod_nss.c +++ b/mod_nss.c @@ -66,6 +66,9 @@ static const command_rec nss_config_cmds[] = { SSL_CMD_SRV(Engine, FLAG, "SSL switch for the protocol engine " "(`on', `off')") + SSL_CMD_SRV(FIPS, FLAG, + "FIPS 140-1 mode " + "(`on', `off')") SSL_CMD_ALL(CipherSuite, TAKE1, "Comma-delimited list of permitted SSL Ciphers, + to enable, - to disable " "(`[+-]XXX,...,[+-]XXX' - see manual)") diff --git a/mod_nss.h b/mod_nss.h index 0813542..bbb65b4 100644 --- a/mod_nss.h +++ b/mod_nss.h @@ -256,6 +256,7 @@ typedef struct { struct SSLSrvConfigRec { SSLModConfigRec *mc; + BOOL fips; BOOL enabled; BOOL proxy_enabled; const char *vhost_id; @@ -311,6 +312,7 @@ void *nss_config_perdir_create(apr_pool_t *p, char *dir); void *nss_config_perdir_merge(apr_pool_t *p, void *basev, void *addv); void *nss_config_server_create(apr_pool_t *p, server_rec *s); void *nss_config_server_merge(apr_pool_t *p, void *basev, void *addv); +const char *nss_cmd_NSSFIPS(cmd_parms *, void *, int); const char *nss_cmd_NSSEngine(cmd_parms *, void *, int); const char *nss_cmd_NSSCertificateDatabase(cmd_parms *cmd, void *dcfg, const char *arg); const char *nss_cmd_NSSDBPrefix(cmd_parms *cmd, void *dcfg, const char *arg); diff --git a/nss_engine_config.c b/nss_engine_config.c index 3600bc9..b4b0c30 100644 --- a/nss_engine_config.c +++ b/nss_engine_config.c @@ -102,6 +102,7 @@ static SSLSrvConfigRec *nss_config_server_new(apr_pool_t *p) SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc)); sc->mc = NULL; + sc->fips = UNSET; sc->enabled = UNSET; sc->proxy_enabled = UNSET; sc->vhost_id = NULL; /* set during module init */ @@ -163,6 +164,7 @@ void *nss_config_server_merge(apr_pool_t *p, void *basev, void *addv) { SSLSrvConfigRec *mrg = nss_config_server_new(p); cfgMerge(mc, NULL); + cfgMergeBool(fips); cfgMergeBool(enabled); cfgMergeBool(proxy_enabled); @@ -263,6 +265,15 @@ const char *nss_cmd_NSSEngine(cmd_parms *cmd, void *dcfg, int flag) return NULL; } +const char *nss_cmd_NSSFIPS(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->fips = flag ? TRUE : FALSE; + + return NULL; +} + const char *nss_cmd_NSSCertificateDatabase(cmd_parms *cmd, void *dcfg, const char *arg) diff --git a/nss_engine_init.c b/nss_engine_init.c index 16d60d6..0a1250d 100644 --- a/nss_engine_init.c +++ b/nss_engine_init.c @@ -16,6 +16,7 @@ #include "mod_nss.h" #include "apr_thread_proc.h" #include "ap_mpm.h" +#include static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket); static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg); @@ -103,7 +104,7 @@ static void nss_add_version_components(apr_pool_t *p, * If sslenabled is not set then there is no need to prompt for the token * passwords. */ -static void nss_init_SSLLibrary(server_rec *s, int sslenabled) +static void nss_init_SSLLibrary(server_rec *s, int sslenabled, int fipsenabled) { SECStatus rv; SSLModConfigRec *mc = myModConfig(s); @@ -117,7 +118,7 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled) /* Do we need to fire up our password helper? */ if (mc->nInitCount == 1 && sslenabled) { - const char * child_argv[3]; + const char * child_argv[4]; apr_status_t rv; if (mc->pphrase_dialog_helper == NULL && @@ -128,9 +129,10 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled) } child_argv[0] = mc->pphrase_dialog_helper; - child_argv[1] = mc->pCertificateDatabase; - child_argv[2] = mc->pDBPrefix; - child_argv[3] = NULL; + child_argv[1] = fipsenabled ? "on" : "off"; + child_argv[2] = mc->pCertificateDatabase; + child_argv[3] = mc->pDBPrefix; + child_argv[4] = NULL; rv = apr_procattr_create(&mc->procattr, mc->pPool); @@ -177,7 +179,32 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled) rv = NSS_Initialize(mc->pCertificateDatabase, mc->pDBPrefix, mc->pDBPrefix, "secmod.db", NSS_INIT_READONLY); /* Assuming everything is ok so far, check the cert database password(s). */ - if (sslenabled && (rv != SECSuccess || nss_Init_Tokens(s) != SECSuccess)) { + if (sslenabled && (rv != SECSuccess)) { + NSS_Shutdown(); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "NSS initialization failed. Certificate database: %s.", mc->pCertificateDatabase != NULL ? mc->pCertificateDatabase : "not set in configuration"); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + + if (fipsenabled) { + if (!PK11_IsFIPS()) { + char * internal_name = PR_smprintf("%s", + SECMOD_GetInternalModule()->commonName); + + if ((SECMOD_DeleteInternalModule(internal_name) != SECSuccess) || + !PK11_IsFIPS()) { + NSS_Shutdown(); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to enable FIPS mode on certificate database %s.", mc->pCertificateDatabase); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + PR_smprintf_free(internal_name); + } /* FIPS is already enabled, nothing to do */ + } + + if (sslenabled && (nss_Init_Tokens(s) != SECSuccess)) { NSS_Shutdown(); ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "NSS initialization failed. Certificate database: %s.", mc->pCertificateDatabase != NULL ? mc->pCertificateDatabase : "not set in configuration"); @@ -200,7 +227,6 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled) SSL_ConfigMPServerSIDCache(mc->session_cache_size, (PRUint32) mc->session_cache_timeout, (PRUint32) mc->ssl3_session_cache_timeout, NULL); else SSL_ConfigServerSessionIDCache(mc->session_cache_size, (PRUint32) mc->session_cache_timeout, (PRUint32) mc->ssl3_session_cache_timeout, NULL); - } int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, @@ -211,6 +237,7 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, SSLSrvConfigRec *sc; server_rec *s; int sslenabled = FALSE; + int fipsenabled = FALSE; mc->nInitCount++; @@ -269,10 +296,24 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, sc->vhost_id_len = strlen(sc->vhost_id); /* Fix up stuff that may not have been set */ + if (sc->fips == UNSET) { + sc->fips = FALSE; + } + + /* If any servers have SSL, we want sslenabled set so we + * can initialize the database. fipsenabled is similar. If + * any of the servers have it set, they all will need to use + * FIPS mode. + */ + if (sc->enabled == UNSET) { sc->enabled = FALSE; } + if (sc->fips == TRUE) { + fipsenabled = TRUE; + } + if (sc->enabled == TRUE) { sslenabled = TRUE; } @@ -282,7 +323,7 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, } } - nss_init_SSLLibrary(base_server, sslenabled); + nss_init_SSLLibrary(base_server, sslenabled, fipsenabled); ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "done Init: Initializing NSS library"); @@ -366,33 +407,39 @@ static void nss_init_ctx_protocol(server_rec *s, ssl2 = ssl3 = tls = 0; - if (mctx->auth.protocols == NULL) { - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "NSSProtocols not set; using: SSLv3 and TLSv1"); + if (mctx->sc->fips) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "In FIPS mode, setting SSLv3 and TLSv1"); ssl3 = tls = 1; } else { - lprotocols = strdup(mctx->auth.protocols); - ap_str_tolower(lprotocols); - - if (strstr(lprotocols, "all") != NULL) { - ssl2 = ssl3 = tls = 1; + if (mctx->auth.protocols == NULL) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + "NSSProtocols not set; using: SSLv3 and TLSv1"); + ssl3 = tls = 1; } else { - if (strstr(lprotocols, "sslv2") != NULL) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling SSL2"); - ssl2 = 1; - } + lprotocols = strdup(mctx->auth.protocols); + ap_str_tolower(lprotocols); - if (strstr(lprotocols, "sslv3") != NULL) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling SSL3"); - ssl3 = 1; - } + if (strstr(lprotocols, "all") != NULL) { + ssl2 = ssl3 = tls = 1; + } else { + if (strstr(lprotocols, "sslv2") != NULL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling SSL2"); + ssl2 = 1; + } - if (strstr(lprotocols, "tlsv1") != NULL) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling TLS"); - tls = 1; + if (strstr(lprotocols, "sslv3") != NULL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling SSL3"); + ssl3 = 1; + } + + if (strstr(lprotocols, "tlsv1") != NULL) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Enabling TLS"); + tls = 1; + } } + free(lprotocols); } - free(lprotocols); } stat = SECSuccess; @@ -520,9 +567,17 @@ static void nss_init_ctx_cipher_suite(server_rec *s, } ciphers = strdup(suite); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + if (mctx->sc->fips) { + free(ciphers); + ciphers = strdup("+fips_3des_sha, +fips_des_sha"); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "FIPS mode, configuring permitted SSL ciphers [%s]", + ciphers); + } else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Configuring permitted SSL ciphers [%s]", suite); + } /* Disable all NSS supported cipher suites. This is to prevent any new * NSS cipher suites from getting automatically and unintentionally diff --git a/nss_pcache.c b/nss_pcache.c index e6e1966..e1c51b1 100644 --- a/nss_pcache.c +++ b/nss_pcache.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "nss_pcache.h" static char * getstr(const char * cmd, int el); @@ -301,12 +302,16 @@ int main(int argc, char ** argv) char * command; char * tokenName; char * tokenpw; + int fipsmode = 0; - if (argc < 2 || argc > 3) { - fprintf(stderr, "Usage: nss_pcache \n"); + if (argc < 3 || argc > 4) { + fprintf(stderr, "Usage: nss_pcache \n"); exit(1); } + if (!strcasecmp(argv[1], "on")) + fipsmode = 1; + /* Initialize NSPR */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); @@ -314,7 +319,23 @@ int main(int argc, char ** argv) PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1); /* Initialize NSS and open the certificate database read-only. */ - rv = NSS_Initialize(argv[1], argc == 3 ? argv[2] : NULL, argc == 3 ? argv[2] : NULL, "secmod.db", NSS_INIT_READONLY); + rv = NSS_Initialize(argv[2], argc == 3 ? argv[3] : NULL, argc == 3 ? argv[3] : NULL, "secmod.db", NSS_INIT_READONLY); + + if (fipsmode) { + if (!PK11_IsFIPS()) { + char * internal_name = PR_smprintf("%s", + SECMOD_GetInternalModule()->commonName); + + if ((SECMOD_DeleteInternalModule(internal_name) != SECSuccess) || + !PK11_IsFIPS()) { + NSS_Shutdown(); + fprintf(stderr, + "Unable to enable FIPS mode"); + exit(1); + } + PR_smprintf_free(internal_name); + } + } in = PR_GetSpecialFD(PR_StandardInput); out = PR_GetSpecialFD(PR_StandardOutput);