bc-java icon indicating copy to clipboard operation
bc-java copied to clipboard

Bouncy Castle FIPS compatibility and errors.

Open minQueue opened this issue 5 years ago • 0 comments

Hi,

I would like to apply Bouncy Castle FIPS TLS1.2 on my application which uses Java7 native code and SDK/JRE8 and Tomcat(7.0.69). Is this possible combination to apply Bouncy Castle FIPS on my application? (If not, would you let me know which one is incompatible and which version I need to update such as Tomcat 8, and Java8 native code? What is an ideal version combination to use BC-FIPS provider with Java application and tomcat?)

If it is possible combination to apply Bouncy Castle FIPS, how do I fix below errors I got? Before adding BC-FIPS providers, I updated the certificate from JKS to BCFKS and changed java.security and java.policy following BC-FIPS guideline. After changing some codes such as sslcontext, keymangerfactory, trustmanagerfactory and so on, I have faced lots of errors below.

  1. SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL
  2. org.bouncycastle.jsse.provider.ProvTlsServer processClientExtensions FINE: Server ignored SNI (no matchers specified)
  3. org.bouncycastle.tls.TlsFatalAlertReceived: certificate_unknown(46)
  4. Server raised fatal(2) internal_error(80) alert: Failed to write record

Full error stack trace:

2020/11/20 12:45:58 [http-bio-20080-exec-4] DEBUG [org.apache.tomcat.util.net.JIoEndpoint] - Handshake failed java.io.IOException: SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL at org.apache.tomcat.util.net.jsse.JSSESocketFactory.handshake(JSSESocketFactory.java:291) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:304) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) 2020/11/20 12:45:58 [http-bio-20080-exec-4] DEBUG [org.apache.tomcat.util.threads.LimitLatch] - Counting down[http-bio-20080-exec-4] latch=2 2020/11/20 12:45:58 [http-bio-20080-Acceptor-0] DEBUG [org.apache.tomcat.util.threads.LimitLatch] - Counting up[http-bio-20080-Acceptor-0] latch=2 Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer getServerVersion FINE: Server selected protocol version: TLSv1.2 Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer getServerVersion FINE: Server selected protocol version: TLSv1.2 Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer processClientExtensions FINE: Server ignored SNI (no matchers specified) Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer getSelectedCipherSuite FINE: Server selected cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer processClientExtensions FINE: Server ignored SNI (no matchers specified) Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer getSelectedCipherSuite FINE: Server selected cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer notifyAlertReceived INFO: Server received fatal(2) certificate_unknown(46) alert Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvSSLSocketDirect getConnection FINE: Failed to establish connection org.bouncycastle.tls.TlsFatalAlertReceived: certificate_unknown(46) at org.bouncycastle.tls.TlsProtocol.handleAlertMessage(Unknown Source) at org.bouncycastle.tls.TlsProtocol.processAlertQueue(Unknown Source) at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source) at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown Source) at org.bouncycastle.tls.TlsServerProtocol.accept(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.handshakeIfNecessary(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getConnection(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getSessionImpl(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getSession(Unknown Source) at org.apache.tomcat.util.net.jsse.JSSESocketFactory.handshake(JSSESocketFactory.java:289) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:304) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

Nov 20, 2020 12:45:58 PM org.bouncycastle.jsse.provider.ProvTlsServer notifyAlertRaised WARNING: Server raised fatal(2) internal_error(80) alert: Failed to write record java.net.SocketException: Software caused connection abort: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) at java.net.SocketOutputStream.write(SocketOutputStream.java:153) at org.bouncycastle.tls.RecordStream.writeRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.safeWriteRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.writeHandshakeMessage(Unknown Source) at org.bouncycastle.tls.HandshakeMessageOutput.send(Unknown Source) at org.bouncycastle.tls.HandshakeMessageOutput.send(Unknown Source) at org.bouncycastle.tls.TlsServerProtocol.sendServerHelloDoneMessage(Unknown Source) at org.bouncycastle.tls.TlsServerProtocol.handleHandshakeMessage(Unknown Source) at org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source) at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source) at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source) at org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown Source) at org.bouncycastle.tls.TlsServerProtocol.accept(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.handshakeIfNecessary(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getConnection(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getSessionImpl(Unknown Source) at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.getSession(Unknown Source) at org.apache.tomcat.util.net.jsse.JSSESocketFactory.handshake(JSSESocketFactory.java:289) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:304) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

Regarding the SNI issue, I tried to apply the second alternative in Endpoint Identification section(3.5.1) https://downloads.bouncycastle.org/fips-java/BC-FJA-(D)TLSUserGuide-1.0.10.pdf Since Java7 does not support SNIHostName class, I used BCSNIHostName, BCSSLParameters, and BCSNIServerName instead of default classes in my code.

try {

		SSLContext context = SSLContext.getInstance("TLSv1.2", new BouncyCastleJsseProvider("fips:BCFIPS"));
		context.init(null, tm, null);
		serverURL = new URL("https://FQDN:port");
		HttpsURLConnection.setDefaultSSLSocketFactory(new org.bouncycastle.jsse.util.CustomSSLSocketFactory(context.getSocketFactory()){
			@Override
			protected Socket configureSocket(Socket s)
			{
				if (s instanceof BCSSLSocket)
				{
					BCSSLSocket bcssl = (BCSSLSocket)s;
					BCSNIHostName bcsniHostName = getSNIHostName(serverURL);
					if (null != bcsniHostName)
					{
						BCSSLParameters bcsslParameters = new BCSSLParameters();
						bcsslParameters.setServerNames(Collections.<BCSNIServerName>singletonList(bcsniHostName));
						bcssl.setParameters(bcsslParameters);
					}
				}
				return s;
			}
		});
	} catch (Exception ex) {
		ex.printStackTrace();
	}

}

private BCSNIHostName getSNIHostName(URL url)
{
	String host = url.getHost();
	if (null != host && host.indexOf('.') > 0 && !org.bouncycastle.util.IPAddress.isValid(host))
	{
		try{
			return new BCSNIHostName(host);
			}
		catch (RuntimeException e){
			// ignore – return null
		}
	}
	return null;
}

I appreciate any comments or solution to figure out above errors.

Thanks

minQueue avatar Dec 17 '20 21:12 minQueue