0

We have application written in java 1.6 we have developed a customized TLSSocketConnection factory based on Bouncy Castle Libraries (v. 1.57)

Here is code snippet of TLSSocketConnection factory

/**
 * This Class enables TLS V1.2  connection based on BouncyCastle Providers.
 */
public class TLSSocketConnectionFactory extends SSLSocketFactory {

    // ******************Adding Custom BouncyCastleProvider*********************//

    static {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
            Security.addProvider(new BouncyCastleProvider());
    }

    // ******************HANDSHAKE LISTENER*********************//

    public class TLSHandshakeListener implements HandshakeCompletedListener {
        @Override
        public void handshakeCompleted(HandshakeCompletedEvent event) {

        }
    }

    private SecureRandom _secureRandom = new SecureRandom();

    // ******************Adding Custom BouncyCastleProvider*********************//

    @Override
    public Socket createSocket(Socket socket, final String host, int port, boolean arg3) throws IOException {
        if (socket == null) {
            socket = new Socket();
        }
        if (!socket.isConnected()) {
            socket.connect(new InetSocketAddress(host, port));
        }

        final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), _secureRandom);
        return _createSSLSocket(host, tlsClientProtocol);
    }

    // ******************SOCKET FACTORY  METHODS*********************//

    @Override
    public String[] getDefaultCipherSuites() {
        return null;
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return null;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return null;
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return null;
    }

    // ******************SOCKET CREATION*********************//

    private SSLSocket _createSSLSocket(final String host, final TlsClientProtocol tlsClientProtocol) {
        return new SSLSocket() {
            private java.security.cert.Certificate[] peertCerts;

            @Override
            public InputStream getInputStream() throws IOException {
                return tlsClientProtocol.getInputStream();
            }

            @Override
            public OutputStream getOutputStream() throws IOException {
                return tlsClientProtocol.getOutputStream();
            }

            @Override
            public synchronized void close() throws IOException {
                tlsClientProtocol.close();
            }

            @Override
            public void addHandshakeCompletedListener(HandshakeCompletedListener arg0) {

            }

            @Override
            public boolean getEnableSessionCreation() {
                return false;
            }

            @Override
            public String[] getEnabledCipherSuites() {
                return null;
            }

            @Override
            public String[] getEnabledProtocols() {
                return null;
            }

            @Override
            public boolean getNeedClientAuth() {
                return false;
            }

            @Override
            public SSLSession getSession() {
                return new SSLSession() {

                    @Override
                    public int getApplicationBufferSize() {
                        return 0;
                    }

                    @Override
                    public String getCipherSuite() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public long getCreationTime() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public byte[] getId() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public long getLastAccessedTime() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public java.security.cert.Certificate[] getLocalCertificates() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public Principal getLocalPrincipal() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public int getPacketBufferSize() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
                        return null;
                    }

                    @Override
                    public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
                        return peertCerts;
                    }

                    @Override
                    public String getPeerHost() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public int getPeerPort() {
                        return 0;
                    }

                    @Override
                    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
                        return null;
                        //throw new UnsupportedOperationException();
                    }

                    @Override
                    public String getProtocol() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public SSLSessionContext getSessionContext() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public Object getValue(String arg0) {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public String[] getValueNames() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void invalidate() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public boolean isValid() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void putValue(String arg0, Object arg1) {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void removeValue(String arg0) {
                        throw new UnsupportedOperationException();
                    }
                };
            }

            @Override
            public String[] getSupportedProtocols() {
                return null;
            }

            @Override
            public boolean getUseClientMode() {
                return false;
            }

            @Override
            public boolean getWantClientAuth() {
                return false;
            }

            @Override
            public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) {
            }

            @Override
            public void setEnableSessionCreation(boolean arg0) {
            }

            @Override
            public void setEnabledCipherSuites(String[] arg0) {
            }

            @Override
            public void setEnabledProtocols(String[] arg0) {
            }

            @Override
            public void setNeedClientAuth(boolean arg0) {
            }

            @Override
            public void setUseClientMode(boolean arg0) {
            }

            @Override
            public void setWantClientAuth(boolean arg0) {
            }

            @Override
            public String[] getSupportedCipherSuites() {
                return null;
            }

            @Override
            public void startHandshake() throws IOException {
                tlsClientProtocol.connect(new DefaultTlsClient() {
                    @Override
                    public Hashtable<Integer, byte[]> getClientExtensions() throws IOException {
                        Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
                        if (clientExtensions == null) {
                            clientExtensions = new Hashtable<Integer, byte[]>();
                        }

                        //Add host_name
                        byte[] host_name = host.getBytes();

                        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        final DataOutputStream dos = new DataOutputStream(baos);
                        dos.writeShort(host_name.length + 3); // entry size
                        dos.writeByte(0); // name type = hostname
                        dos.writeShort(host_name.length);
                        dos.write(host_name);
                        dos.close();
                        clientExtensions.put(ExtensionType.server_name, baos.toByteArray());
                        return clientExtensions;
                    }

                    @Override
                    public TlsAuthentication getAuthentication() throws IOException {
                        return new TlsAuthentication() {
                            @Override
                            public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
                                try {
                                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
                                    List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>();
                                    for (org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) {
                                        certs.add(cf.generateCertificate(new ByteArrayInputStream(c.getEncoded())));
                                    }
                                    peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
                                } catch (CertificateException e) {
                                    System.out.println("Failed to cache server certs" + e);
                                    throw new IOException(e);
                                }
                            }

                            @Override
                            public TlsCredentials getClientCredentials(CertificateRequest arg0) throws IOException {
                                return null;
                            }
                        };
                    }
                });
            }
        };//Socket

    }
}

The way we use it

HttpClient httpclient = HttpClientBuilder.create().setDefaultRequestConfig(getRequestConfig()).setRedirectStrategy(new LaxRedirectStrategy()).setSSLSocketFactory(getSSLContext()).build();
        logger.info(httpclient.toString());
        HttpClientContext context = getHttpContext();

        HttpPost httppost = new HttpPost(urlString);
        HttpResponse httpResponse = httpclient.execute(httppost, context);

private RequestConfig getRequestConfig() {
        return RequestConfig.custom().setConnectTimeout(320 * 1000).setConnectionRequestTimeout(320 * 1000).setSocketTimeout(320 * 1000).build();
    }

    private SSLConnectionSocketFactory getSSLContext() throws Exception {
        return new SSLConnectionSocketFactory(new TLSSocketConnectionFactory(), new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    }

With this I end up getting error in logs as

Exception: : java.io.IOException: Internal TLS error, this could be an attack
    at org.bouncycastle.crypto.tls.TlsProtocol.failWithError(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsProtocol.safeReadRecord(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsProtocol.readApplicationData(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsInputStream.read(Unknown Source) [:1.57.0]
    at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136) [:4.3.3]

Any idea how to fix it? Is it due to LaxRedirectStrategy or setting SSL socket connection timeout? Its hard to figure out how to approach the issue. Rather where to start to solve this.

Shivraj
  • 462
  • 2
  • 9
  • 27
  • 1
    Could you try if [tls12 java16 bouncycastle](https://stackoverflow.com/questions/33517476/tls-1-2-java-1-6-bouncycastle) solves your problem? The answer proposes to overwrite `allowUnexpectedServerExtension` – Andre Albert Feb 09 '18 at 20:08
  • 1
    You're building a security related application ... on top of Java 1.6??? – Maarten Bodewes Feb 10 '18 at 22:46

1 Answers1

1

Ok. To update everyone, the issue has been fixed by below settings

  1. getting latest jar( bcprov-jdk15on-159.jar) from http://www.bouncycastle.org/latest_releases.html

I replaced v1.57 by v 1.59 and that solved the issue.

  1. private RequestConfig getRequestConfig() { return RequestConfig.custom().setSocketTimeout(320 * 1000).build(); }

Shivraj
  • 462
  • 2
  • 9
  • 27