4589N/A/*
4589N/A * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
4589N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4589N/A *
4589N/A * This code is free software; you can redistribute it and/or modify it
4589N/A * under the terms of the GNU General Public License version 2 only, as
4589N/A * published by the Free Software Foundation.
4589N/A *
4589N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4589N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4589N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4589N/A * version 2 for more details (a copy is included in the LICENSE file that
4589N/A * accompanied this code).
4589N/A *
4589N/A * You should have received a copy of the GNU General Public License version
4589N/A * 2 along with this work; if not, write to the Free Software Foundation,
4589N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4589N/A *
4589N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4589N/A * or visit www.oracle.com if you need additional information or have any
4589N/A * questions.
4589N/A */
4589N/A
4589N/Aimport java.io.*;
4589N/Aimport java.net.*;
4589N/Aimport java.util.*;
4589N/Aimport java.security.*;
4589N/Aimport javax.net.*;
4589N/Aimport javax.net.ssl.*;
4589N/Aimport java.lang.reflect.*;
4589N/A
5706N/Aimport sun.security.util.KeyUtil;
4589N/A
4589N/Apublic class ShortRSAKeyWithinTLS {
4589N/A
4589N/A /*
4589N/A * =============================================================
4589N/A * Set the various variables needed for the tests, then
4589N/A * specify what tests to run on each side.
4589N/A */
4589N/A
4589N/A /*
4589N/A * Should we run the client or server in a separate thread?
4589N/A * Both sides can throw exceptions, but do you have a preference
4589N/A * as to which side should be the main thread.
4589N/A */
4589N/A static boolean separateServerThread = false;
4589N/A
4589N/A /*
4589N/A * Is the server ready to serve?
4589N/A */
4589N/A volatile static boolean serverReady = false;
4589N/A
4589N/A /*
4589N/A * Turn on SSL debugging?
4589N/A */
4589N/A static boolean debug = false;
4589N/A
4589N/A /*
4589N/A * If the client or server is doing some kind of object creation
4589N/A * that the other side depends on, and that thread prematurely
4589N/A * exits, you may experience a hang. The test harness will
4589N/A * terminate all hung threads after its timeout has expired,
4589N/A * currently 3 minutes by default, but you might try to be
4589N/A * smart about it....
4589N/A */
4589N/A
4589N/A /*
4589N/A * Define the server side of the test.
4589N/A *
4589N/A * If the server prematurely exits, serverReady will be set to true
4589N/A * to avoid infinite hangs.
4589N/A */
4589N/A void doServerSide() throws Exception {
4589N/A
4589N/A // load the key store
4589N/A KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
4589N/A ks.load(null, null);
4589N/A System.out.println("Loaded keystore: Windows-MY");
4589N/A
4589N/A // check key size
4589N/A checkKeySize(ks);
4589N/A
4589N/A // initialize the SSLContext
4589N/A KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
4589N/A kmf.init(ks, null);
4589N/A
4589N/A TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
4589N/A tmf.init(ks);
4589N/A
4589N/A SSLContext ctx = SSLContext.getInstance("TLS");
4589N/A ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
4589N/A
4589N/A ServerSocketFactory ssf = ctx.getServerSocketFactory();
4589N/A SSLServerSocket sslServerSocket = (SSLServerSocket)
4589N/A ssf.createServerSocket(serverPort);
4589N/A sslServerSocket.setNeedClientAuth(true);
4589N/A serverPort = sslServerSocket.getLocalPort();
4589N/A System.out.println("serverPort = " + serverPort);
4589N/A
4589N/A /*
4589N/A * Signal Client, we're ready for his connect.
4589N/A */
4589N/A serverReady = true;
4589N/A
4589N/A SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
4589N/A InputStream sslIS = sslSocket.getInputStream();
4589N/A OutputStream sslOS = sslSocket.getOutputStream();
4589N/A
4589N/A sslIS.read();
4589N/A sslOS.write(85);
4589N/A sslOS.flush();
4589N/A
4589N/A sslSocket.close();
4589N/A }
4589N/A
4589N/A /*
4589N/A * Define the client side of the test.
4589N/A *
4589N/A * If the server prematurely exits, serverReady will be set to true
4589N/A * to avoid infinite hangs.
4589N/A */
4589N/A void doClientSide() throws Exception {
4589N/A
4589N/A /*
4589N/A * Wait for server to get started.
4589N/A */
4589N/A while (!serverReady) {
4589N/A Thread.sleep(50);
4589N/A }
4589N/A
4589N/A // load the key store
4589N/A KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
4589N/A ks.load(null, null);
4589N/A System.out.println("Loaded keystore: Windows-MY");
4589N/A
4589N/A // initialize the SSLContext
4589N/A KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
4589N/A kmf.init(ks, null);
4589N/A
4589N/A TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
4589N/A tmf.init(ks);
4589N/A
4589N/A SSLContext ctx = SSLContext.getInstance("TLS");
4589N/A ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
4589N/A
4589N/A SSLSocketFactory sslsf = ctx.getSocketFactory();
4589N/A SSLSocket sslSocket = (SSLSocket)
4589N/A sslsf.createSocket("localhost", serverPort);
4589N/A
4589N/A if (clientProtocol != null) {
4589N/A sslSocket.setEnabledProtocols(new String[] {clientProtocol});
4589N/A }
4589N/A
4589N/A if (clientCiperSuite != null) {
4589N/A sslSocket.setEnabledCipherSuites(new String[] {clientCiperSuite});
4589N/A }
4589N/A
4589N/A InputStream sslIS = sslSocket.getInputStream();
4589N/A OutputStream sslOS = sslSocket.getOutputStream();
4589N/A
4589N/A sslOS.write(280);
4589N/A sslOS.flush();
4589N/A sslIS.read();
4589N/A
4589N/A sslSocket.close();
4589N/A }
4589N/A
4589N/A private void checkKeySize(KeyStore ks) throws Exception {
4589N/A PrivateKey privateKey = null;
4589N/A PublicKey publicKey = null;
4589N/A
4589N/A if (ks.containsAlias(keyAlias)) {
4589N/A System.out.println("Loaded entry: " + keyAlias);
4589N/A privateKey = (PrivateKey)ks.getKey(keyAlias, null);
4589N/A publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey();
4589N/A
5706N/A int privateKeySize = KeyUtil.getKeySize(privateKey);
4589N/A if (privateKeySize != keySize) {
4589N/A throw new Exception("Expected key size is " + keySize +
4589N/A ", but the private key size is " + privateKeySize);
4589N/A }
4589N/A
5706N/A int publicKeySize = KeyUtil.getKeySize(publicKey);
4589N/A if (publicKeySize != keySize) {
4589N/A throw new Exception("Expected key size is " + keySize +
4589N/A ", but the public key size is " + publicKeySize);
4589N/A }
4589N/A }
4589N/A }
4589N/A
4589N/A /*
4589N/A * =============================================================
4589N/A * The remainder is just support stuff
4589N/A */
4589N/A
4589N/A // use any free port by default
4589N/A volatile int serverPort = 0;
4589N/A
4589N/A volatile Exception serverException = null;
4589N/A volatile Exception clientException = null;
4589N/A
4589N/A private static String keyAlias;
4589N/A private static int keySize;
4589N/A private static String clientProtocol = null;
4589N/A private static String clientCiperSuite = null;
4589N/A
4589N/A private static void parseArguments(String[] args) {
4589N/A keyAlias = args[0];
4589N/A keySize = Integer.parseInt(args[1]);
4589N/A
4589N/A if (args.length > 2) {
4589N/A clientProtocol = args[2];
4589N/A }
4589N/A
4589N/A if (args.length > 3) {
4589N/A clientCiperSuite = args[3];
4589N/A }
4589N/A }
4589N/A
4589N/A public static void main(String[] args) throws Exception {
4589N/A if (debug) {
4589N/A System.setProperty("javax.net.debug", "all");
4589N/A }
4589N/A
4589N/A // Get the customized arguments.
4589N/A parseArguments(args);
4589N/A
4589N/A new ShortRSAKeyWithinTLS();
4589N/A }
4589N/A
4589N/A Thread clientThread = null;
4589N/A Thread serverThread = null;
4589N/A
4589N/A /*
4589N/A * Primary constructor, used to drive remainder of the test.
4589N/A *
4589N/A * Fork off the other side, then do your work.
4589N/A */
4589N/A ShortRSAKeyWithinTLS() throws Exception {
4589N/A try {
4589N/A if (separateServerThread) {
4589N/A startServer(true);
4589N/A startClient(false);
4589N/A } else {
4589N/A startClient(true);
4589N/A startServer(false);
4589N/A }
4589N/A } catch (Exception e) {
4589N/A // swallow for now. Show later
4589N/A }
4589N/A
4589N/A /*
4589N/A * Wait for other side to close down.
4589N/A */
4589N/A if (separateServerThread) {
4589N/A serverThread.join();
4589N/A } else {
4589N/A clientThread.join();
4589N/A }
4589N/A
4589N/A /*
4589N/A * When we get here, the test is pretty much over.
4589N/A * Which side threw the error?
4589N/A */
4589N/A Exception local;
4589N/A Exception remote;
4589N/A String whichRemote;
4589N/A
4589N/A if (separateServerThread) {
4589N/A remote = serverException;
4589N/A local = clientException;
4589N/A whichRemote = "server";
4589N/A } else {
4589N/A remote = clientException;
4589N/A local = serverException;
4589N/A whichRemote = "client";
4589N/A }
4589N/A
4589N/A /*
4589N/A * If both failed, return the curthread's exception, but also
4589N/A * print the remote side Exception
4589N/A */
4589N/A if ((local != null) && (remote != null)) {
4589N/A System.out.println(whichRemote + " also threw:");
4589N/A remote.printStackTrace();
4589N/A System.out.println();
4589N/A throw local;
4589N/A }
4589N/A
4589N/A if (remote != null) {
4589N/A throw remote;
4589N/A }
4589N/A
4589N/A if (local != null) {
4589N/A throw local;
4589N/A }
4589N/A }
4589N/A
4589N/A void startServer(boolean newThread) throws Exception {
4589N/A if (newThread) {
4589N/A serverThread = new Thread() {
4589N/A public void run() {
4589N/A try {
4589N/A doServerSide();
4589N/A } catch (Exception e) {
4589N/A /*
4589N/A * Our server thread just died.
4589N/A *
4589N/A * Release the client, if not active already...
4589N/A */
4589N/A System.err.println("Server died...");
4589N/A serverReady = true;
4589N/A serverException = e;
4589N/A }
4589N/A }
4589N/A };
4589N/A serverThread.start();
4589N/A } else {
4589N/A try {
4589N/A doServerSide();
4589N/A } catch (Exception e) {
4589N/A serverException = e;
4589N/A } finally {
4589N/A serverReady = true;
4589N/A }
4589N/A }
4589N/A }
4589N/A
4589N/A void startClient(boolean newThread) throws Exception {
4589N/A if (newThread) {
4589N/A clientThread = new Thread() {
4589N/A public void run() {
4589N/A try {
4589N/A doClientSide();
4589N/A } catch (Exception e) {
4589N/A /*
4589N/A * Our client thread just died.
4589N/A */
4589N/A System.err.println("Client died...");
4589N/A clientException = e;
4589N/A }
4589N/A }
4589N/A };
4589N/A clientThread.start();
4589N/A } else {
4589N/A try {
4589N/A doClientSide();
4589N/A } catch (Exception e) {
4589N/A clientException = e;
4589N/A }
4589N/A }
4589N/A }
4589N/A}
4589N/A