--- java/org/apache/catalina/core/LocalStrings.properties (revision 1140778) +++ java/org/apache/catalina/core/LocalStrings.properties (working copy) @@ -59,6 +59,13 @@ aprListener.sslInit=Failed to initialize the SSLEngine. aprListener.tcnValid=Loaded APR based Apache Tomcat Native library {0}. aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}]. +aprListener.initializingFIPS=Initializing FIPS mode... +aprListener.initializeFIPSSuccess=Successfully entered FIPS mode +aprListener.initializeFIPSFailed=Failed to enter FIPS mode +aprListener.tooLateForSSLEngine=Cannot setSSLEngine: SSL has already been initialized +aprListener.tooLateForSSLRandomSeed=Cannot setSSLRandomSeed: SSL has already been initialized +aprListener.tooLateForFIPSMode=Cannot setFIPSMode: SSL has already been initialized + asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing. containerBase.alreadyStarted=Container {0} has already been started containerBase.notConfigured=No basic Valve has been configured --- java/org/apache/catalina/core/AprLifecycleListener.java (revision 1140788) +++ java/org/apache/catalina/core/AprLifecycleListener.java (working copy) @@ -66,11 +66,13 @@ // ---------------------------------------------- Properties protected static String SSLEngine = "on"; //default on + protected static String FIPSMode = "off"; // default off, valid only when SSLEngine="on" protected static String SSLRandomSeed = "builtin"; protected static boolean sslInitialized = false; protected static boolean aprInitialized = false; protected static boolean sslAvailable = false; protected static boolean aprAvailable = false; + protected static boolean fipsModeActive = false; protected static final Object lock = new Object(); @@ -138,6 +140,7 @@ aprInitialized = false; sslInitialized = false; // Well we cleaned the pool in terminate. sslAvailable = false; // Well we cleaned the pool in terminate. + fipsModeActive = false; } private static void init() @@ -231,20 +234,85 @@ Method method = clazz.getMethod(methodName, paramTypes); method.invoke(null, paramValues); - methodName = "initialize"; paramValues[0] = "on".equalsIgnoreCase(SSLEngine)?null:SSLEngine; method = clazz.getMethod(methodName, paramTypes); method.invoke(null, paramValues); + if("on".equalsIgnoreCase(AprLifecycleListener.FIPSMode)) + { + log.info(sm.getString("aprListener.initializingFIPS")); + + boolean success = initializeFIPS(); + + if(success) + { + log.info(sm.getString("aprListener.initializeFIPSSuccess")); + } + else + { + String errMsg = sm.getString("aprListener.initializeFIPSFailed"); + log.error(errMsg); + + // Do not set sslAvailable=true if FIPS mode fails + // TODO: Allow initializeFIPS to throw it's own exception + // including a real descriptive error message + throw new InvocationTargetException(null, errMsg); + } + } + sslAvailable = true; } + /** + * Initialize FIPS mode in a way that won't crash if the FIPS libtcnative + * and associated libraries are not available. + * + * @param initializeFIPS + * @return + */ + private static boolean initializeFIPS() + throws NoSuchMethodException + { + try + { + Class clazz = Class.forName("org.apache.tomcat.jni.SSL"); + String methodName = "fipsModeSet"; + Method method = clazz.getMethod(methodName, new Class[]{Integer.class}); + Object[] fipsParamValues = new Object[]{Integer.valueOf(1)}; + Object result = method.invoke(null, fipsParamValues); + + if(result instanceof Integer) + { + // success is defined as return value = 1 + fipsModeActive = (1 == ((Integer)result).intValue()); + + return fipsModeActive; + } + else + log.info( sm.getString("aprListener.fipsModeSetInvalid") ); + } + catch(InvocationTargetException ite) + { + log.info(sm.getString("aprListener.fipsModeUnavailable") + ": " + ite.getMessage()); + } + catch (Throwable t) + { + log.error(sm.getString("aprListener.initializeFIPSFailed", System.getProperty("java.library.path")), t); + } + + return false; + } + public String getSSLEngine() { return SSLEngine; } public void setSSLEngine(String SSLEngine) { + // Ensure that the SSLEngine is consistent with that used for SSL init + if(sslInitialized) + throw new IllegalStateException(sm.getString("aprListener.tooLateForSSLEngine")); + AprLifecycleListener.SSLEngine = SSLEngine; } @@ -253,7 +321,24 @@ } public void setSSLRandomSeed(String SSLRandomSeed) { + // Ensure that the random seed is consistent with that used for SSL init + if(sslInitialized) + throw new IllegalStateException(sm.getString("aprListener.tooLateForSSLRandomSeed")); + AprLifecycleListener.SSLRandomSeed = SSLRandomSeed; } + public void setFIPSMode(String FIPSMode) + { + // Ensure that the FIPS mode is consistent with that used for SSL init + if(sslInitialized) + throw new IllegalStateException(sm.getString("aprListener.tooLateForFIPSMode")); + + AprLifecycleListener.FIPSMode = FIPSMode; + } + + public boolean isFIPSModeActive() + { + return fipsModeActive; + } } --- java/org/apache/tomcat/jni/SSL.java (revision 1140778) +++ java/org/apache/tomcat/jni/SSL.java (working copy) @@ -230,6 +230,20 @@ public static native int initialize(String engine); /** + * Enable/Disable FIPS Mode. + * + * @param mode 1 - enable, 0 - disable + * + * @return FIPS_mode_set return code + */ + public static int fipsModeSet(Integer mode) + { + return fipsModeSet(mode.intValue()); + } + + public static native int fipsModeSet(int mode); + + /** * Add content of the file to the PRNG * @param filename Filename containing random data. * If null the default file will be tested.