0

I am trying to achieve the following security rule

server must generate a unique session identifier using a FIPS 140-2 approved random number generator.

I am using Tomcat 7.0.68 for my server, I am unable to find any information on if the generating of the session IDs for tomcat are FIPS compliant.

Does anyone know if the Session ID generator for Tomcat is FIPS compliant and if not if it is possible to use a FIPS compliant random number generator with Tomcat?

2

There is a FIPSMode configuration option in Tomcat's APR Lifecycle Listener, which looks like it would fulfill your requirements. As observed in this very similar StackOverflow thread, and Tomcat/APR Lifecycle Listener documentation, it's really about the operating mode of OpenSSL, not Tomcat.

On a not-unrelated note, Tomcat isn't FIPS-certified, due to the cost, time and red-tape involved in FIPS-certification, however, there are some commercial offerings that have tested Tomcat with FIPS-compliant JSSE providers, which may be sufficient for your purposes. Additionally, Oracle and IBM both provide documentation on enabling FIPS mode/compliance with the JSSEs they provide, so it may not be necessary to use a 3rd-party offering, again, depending on your requirements.

On the specific question on Tomcat's Session ID generator, since it's open-source, we can check, and it appears that Tomcat's SessionID Generator uses Java's SecureRandom library, which "[...] complies with the statistical random number generator tests specified in FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.1."

public class SessionIdGenerator {

/**
 * Generate and return a new session identifier.
 */
public String generateSessionId() {
byte random[] = new byte[16];
// Render the result as a String of hexadecimal digits
StringBuilder buffer = new StringBuilder();
int resultLenBytes = 0;

while (resultLenBytes < sessionIdLength) {
getRandomBytes(random);
for (int j = 0; j < random.length && resultLenBytes < sessionIdLength; j++) {
byte b1 = (byte) ((random[j] & 0xf0) >> 4);
byte b2 = (byte) (random[j] & 0x0f);

if (b1 < 10) buffer.append((char) ('0' + b1));
else buffer.append((char) ('A' + (b1 - 10)));

if (b2 < 10) buffer.append((char) ('0' + b2));
else buffer.append((char) ('A' + (b2 - 10)));

resultLenBytes++;
 }
 }

if (jvmRoute != null && jvmRoute.length() > 0) {
 buffer.append('.').append(jvmRoute);
 }

return buffer.toString();
 }

/**
 *
 */
 private void getRandomBytes(byte bytes[]) {
SecureRandom random = randoms.poll();
 if (random == null) {
 random = createSecureRandom();
 }
 random.nextBytes(bytes);
 randoms.add(random);
 }

 /**
 * Create a new random number generator instance we should use for
 * generating session identifiers.
 */
 private SecureRandom createSecureRandom() {

SecureRandom result = null;

long t1 = System.currentTimeMillis();
 if (secureRandomClass != null) {
 try {
 // Construct and seed a new random number generator
 Class<?> clazz = Class.forName(secureRandomClass);
 result = (SecureRandom) clazz.newInstance();
 } catch (Exception e) {
 log.error(sm.getString("sessionIdGenerator.random",
 secureRandomClass), e);
 }
 }

if (result == null) {
 // No secureRandomClass or creation failed. Use SecureRandom.
 try {
 if (secureRandomProvider != null &&
 secureRandomProvider.length() > 0) {
 result = SecureRandom.getInstance(secureRandomAlgorithm,
 secureRandomProvider);
 } else if (secureRandomAlgorithm != null &&
 secureRandomAlgorithm.length() > 0) {
 result = SecureRandom.getInstance(secureRandomAlgorithm);
 }
 } catch (NoSuchAlgorithmException e) {
 log.error(sm.getString("sessionIdGenerator.randomAlgorithm",
 secureRandomAlgorithm), e);
 } catch (NoSuchProviderException e) {
 log.error(sm.getString("sessionIdGenerator.randomProvider",
 secureRandomProvider), e);
 }
 }

if (result == null) {
 // Invalid provider / algorithm
 try {
 result = SecureRandom.getInstance("SHA1PRNG");
 } catch (NoSuchAlgorithmException e) {
 log.error(sm.getString("sessionIdGenerator.randomAlgorithm",
 secureRandomAlgorithm), e);
 }
 }

if (result == null) {
 // Nothing works - use platform default
 result = new SecureRandom();
 }

// Force seeding to take place
 result.nextInt();

long t2 = System.currentTimeMillis();
 if ((t2 - t1) > 100)
 log.info(sm.getString("sessionIdGenerator.createRandom",
 result.getAlgorithm(), Long.valueOf(t2 - t1)));
 return result;
 }

}
  • I believe your answer is focusing on SSL/TLS management and its relationship with FIPS 140-2, while jgr208's question is related to PRNG used for session ID generation. – PwdRsch Jun 17 '16 at 15:53
  • 1
    Yes looking through source code I got that too that it uses the java secure class to generate the numbers and that, that class is FIPS compliant so I will be able to use that when I talk with the folks in charge of inspecting our system. Thanks. – jgr208 Jun 20 '16 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.