/* ClientJSSE.java * * Copyright (C) 2006-2025 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.Provider; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.Arrays; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import com.wolfssl.WolfSSLDebug; import com.wolfssl.provider.jsse.WolfSSLProvider; import com.wolfssl.WolfSSL; import java.security.PrivateKey; import java.security.Security; import javax.net.ssl.KeyManager; import javax.net.ssl.X509KeyManager; import java.security.cert.X509Certificate; import java.security.cert.Certificate; public class ClientJSSE { public ClientJSSE() { } public void run(String[] args) throws Exception { int ret = 0, input; byte[] back = new byte[1024]; String readString = null; String msg = "Too legit to quit"; /* HTTP GET Host appended after command line args */ String httpGetMsg = "GET / HTTP/1.1"; String provider = "wolfJSSE"; KeyStore pKey, cert; TrustManagerFactory tm = null; KeyManagerFactory km = null; ServerSocketFactory srv; ServerSocket tls; SSLContext ctx; BufferedReader inReader = null; OutputStream outStream = null; /* config info */ String version; String cipherList = null; /* default ciphersuite list */ int sslVersion = 3; /* default to TLS 1.2 */ boolean verifyPeer = true; /* verify peer by default */ boolean useSysRoots = false; /* skip CA KeyStore load, use system default roots */ boolean useEnvVar = false; /* load cert/key from enviornment variable */ boolean listSuites = false; /* list all supported cipher suites */ boolean listEnabledProtocols = false; /* show enabled protocols */ boolean putEnabledProtocols = false; /* set enabled protocols */ boolean sendGET = false; /* send HTTP GET */ /* Sleep 10 seconds before and after execution of main example, * to allow profilers like VisualVM to be attached. */ boolean profileSleep = false; boolean resumeSession = false; /* try one session resumption */ byte[] firstSessionId = null; /* sess ID of first session */ byte[] resumeSessionId = null; /* sess ID of resumed session */ /* cert info */ String clientJKS = "../provider/client.jks"; String caJKS = "../provider/ca-server.jks"; String clientPswd = "wolfSSL test"; String caPswd = "wolfSSL test"; String keyStoreFormat = "JKS"; /* server (peer) info */ String host = "localhost"; int port = 11111; /* set/get enabled protocols */ String[] protocols = null; /* pull in command line options from user */ for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("-?")) { printUsage(); } else if (arg.equals("-h")) { if (args.length < i+2) printUsage(); host = args[++i]; } else if (arg.equals("-p")) { if (args.length < i+2) printUsage(); port = Integer.parseInt(args[++i]); } else if (arg.equals("-v")) { if (args.length < i+2) printUsage(); if (args[i+1].equals("d")) { i++; sslVersion = -1; } else { sslVersion = Integer.parseInt(args[++i]); if (sslVersion < 0 || sslVersion > 4) { printUsage(); } } } else if (arg.equals("-l")) { if (args.length < i+2) printUsage(); cipherList = args[++i]; } else if (arg.equals("-c")) { String[] tmp = args[++i].split(":"); if (tmp.length != 2) { printUsage(); } clientJKS = tmp[0]; clientPswd = tmp[1]; } else if (arg.equals("-A")) { String[] tmp = args[++i].split(":"); if (tmp.length != 2) { printUsage(); } caJKS = tmp[0]; caPswd = tmp[1]; } else if (arg.equals("-d")) { verifyPeer = false; } else if (arg.equals("-g")) { sendGET = true; } else if (arg.equals("-e")) { listSuites = true; } else if (arg.equals("-env")) { useEnvVar = true; } else if (arg.equals("-getp")) { listEnabledProtocols = true; } else if (arg.equals("-setp")) { putEnabledProtocols = true; protocols = args[++i].split(" "); sslVersion = -1; } else if (arg.equals("-r")) { resumeSession = true; } else if (arg.equals("-profile")) { profileSleep = true; } else if (arg.equals("-sysca")) { useSysRoots = true; } else if (arg.equals("-ksformat")) { keyStoreFormat = args[++i]; } else { printUsage(); } } switch (sslVersion) { case -1: version = "TLS"; break; case 0: version = "SSLv3"; break; case 1: version = "TLSv1"; break; case 2: version = "TLSv1.1"; break; case 3: version = "TLSv1.2"; break; case 4: version = "TLSv1.3"; break; default: printUsage(); return; } /* Add host into HTTP GET */ httpGetMsg = String.format("%s\r\nHost: %s\r\n\r\n", httpGetMsg, host); if (profileSleep) { System.out.println( "Sleeping 10 seconds to allow profiler to attach"); Thread.sleep(10000); } /* X509TrustManager that trusts all peer certificates. Used if peer * authentication (-d) has been passed in */ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public void checkClientTrusted( X509Certificate[] chain, String authType) { } public void checkServerTrusted( X509Certificate[] chain, String authType) { } public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } } }; /* trust manager (certificates) */ if (verifyPeer) { tm = TrustManagerFactory.getInstance("SunX509", provider); if (useSysRoots) { /* Let wolfJSSE try to find/load default system CA certs */ tm.init((KeyStore)null); } else { cert = KeyStore.getInstance(keyStoreFormat); cert.load(new FileInputStream(caJKS), caPswd.toCharArray()); tm.init(cert); } } /* load private key */ pKey = KeyStore.getInstance(keyStoreFormat); pKey.load(new FileInputStream(clientJKS), clientPswd.toCharArray()); km = KeyManagerFactory.getInstance("SunX509", provider); km.init(pKey, clientPswd.toCharArray()); /* setup context with certificate and private key */ ctx = SSLContext.getInstance(version, provider); if (verifyPeer) { ctx.init(km.getKeyManagers(), tm.getTrustManagers(), null); } else { ctx.init(km.getKeyManagers(), trustAllCerts, null); } if (listSuites) { String[] suites = ctx.getDefaultSSLParameters().getCipherSuites(); for (String x : suites) { System.out.println("\t" + x); } return; } SocketFactory sf = ctx.getSocketFactory(); /* print enabled protocols if requested */ if (listEnabledProtocols) { SSLSocket sk = (SSLSocket)sf.createSocket(); String[] prtolists = sk.getEnabledProtocols(); for (String str : prtolists) { System.out.println("\t" + str); } return; } SSLSocket sock = (SSLSocket)sf.createSocket(host, port); /* put enabled protocols if requested */ if (putEnabledProtocols) { if(protocols != null) sock.setEnabledProtocols(protocols); } System.out.printf("Using SSLContext provider %s\n", ctx.getProvider(). getName()); if (cipherList != null) { sock.setEnabledCipherSuites(cipherList.split(":")); } sock.startHandshake(); firstSessionId = sock.getSession().getId(); showPeer(sock); inReader = new BufferedReader( new InputStreamReader(sock.getInputStream())); outStream = sock.getOutputStream(); if (sendGET) { outStream.write(httpGetMsg.getBytes()); } else { outStream.write(msg.getBytes()); } System.out.println("Server message : "); while ((readString = inReader.readLine()) != null) { System.out.println(readString); } inReader.close(); outStream.close(); sock.close(); if (resumeSession) { System.out.println("\nTrying session resumption..."); sock = (SSLSocket)sf.createSocket(host, port); if (putEnabledProtocols) { if(protocols != null) sock.setEnabledProtocols(protocols); } System.out.printf("Using SSLContext provider %s\n", ctx.getProvider().getName()); if (cipherList != null) { sock.setEnabledCipherSuites(cipherList.split(":")); } sock.startHandshake(); resumeSessionId = sock.getSession().getId(); showPeer(sock); inReader = new BufferedReader( new InputStreamReader(sock.getInputStream())); outStream = sock.getOutputStream(); if (Arrays.equals(firstSessionId, resumeSessionId)) { System.out.println("Session resumed"); } else { System.out.println("Session NOT resumed"); } if (sendGET) { outStream.write(httpGetMsg.getBytes()); } else { outStream.write(msg.getBytes()); } System.out.println("Server message : "); while ((readString = inReader.readLine()) != null) { System.out.println(readString); } inReader.close(); outStream.close(); sock.close(); } if (profileSleep) { /* Remove provider and set variables to null to help garbage * collector for profiling */ Security.removeProvider("wolfJSSE"); sock = null; sf = null; ctx = null; km = null; tm = null; /* Try and kick start garbage collector before profiling * heap dump */ System.gc(); System.out.println( "Sleeping 10 seconds to allow profiler to dump heap"); Thread.sleep(10000); } } private void showPeer(SSLSocket sock) { int i = 0; byte[] sessionId = null; SSLSession session = sock.getSession(); System.out.println("SSL version is " + session.getProtocol()); System.out.println("SSL cipher suite is " + session.getCipherSuite()); sessionId = session.getId(); if (sessionId != null) { System.out.format("Session ID (%d bytes): ", sessionId.length); for (i = 0; i < sessionId.length; i++) { System.out.format("%02x", sessionId[i]); } System.out.println(""); } System.out.println("Session created: " + session.getCreationTime()); System.out.println("Session accessed: " + session.getLastAccessedTime()); if (WolfSSLDebug.DEBUG) { try { Certificate[] certs = session.getPeerCertificates(); if (certs != null && certs.length > 0) { System.out.println(((X509Certificate)certs[0]).toString()); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { WolfSSL.loadLibrary(); Security.addProvider(new WolfSSLProvider()); ClientJSSE client = new ClientJSSE(); try { client.run(args); } catch (Exception ex) { ex.printStackTrace(); } } private void printUsage() { System.out.println("Java wolfJSSE example client usage:"); System.out.println("-?\t\tHelp, print this usage"); System.out.println("-h \tHost to connect to, default 127.0.0.1"); System.out.println("-p \tPort to connect to, default 11111"); System.out.println("-v \tSSL version [0-4], SSLv3(0) - " + "TLS1.3(4)), default 3 : use 'd' for downgrade"); System.out.println("-l \tCipher list"); System.out.println("-d\t\tDisable peer checks"); System.out.println("-g\t\tSend server HTTP GET"); System.out.println("-e\t\tGet all supported cipher suites"); System.out.println("-r\t\tResume session"); System.out.println("-sysca\t\tLoad system CA certs, ignore any passed in"); System.out.println("-getp\t\tGet enabled protocols"); System.out.println("-setp \tSet enabled protocols " + "e.g \"TLSv1.1 TLSv1.2\""); System.out.println("-c :\tCertificate/key JKS,\t\tdefault " + "../provider/client.jks:\"wolfSSL test\""); System.out.println("-A :\tCertificate/key CA JKS file,\tdefault " + "../provider/ca-server.jks:\"wolfSSL test\""); System.out.println("-profile\tSleep for 10 sec before/after running " + "to allow profilers to attach"); System.out.println("-ksformat \tKeyStore format (default: JKS)"); System.exit(1); } }