/*
 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6690018
 * @summary RSAClientKeyExchange NullPointerException
 */

/*
 * Certificates and key used in the test.
 *
 * TLS server certificate:
 * server private key:
 * -----BEGIN RSA PRIVATE KEY-----
 * Proc-Type: 4,ENCRYPTED
 * DEK-Info: DES-EDE3-CBC,97EC03A2D031B7BC
 *
 * 22wrD+DPv3VF8xg9xoeBqHzFnOVbTLQgVulzaCECDF4zWdxElYKy4yYyY6dMDehi
 * XT77NTsq1J14zjJHPp2/U6B5OpZxnf97ZSD0ZC9/DDe/2gjW4fY1Lv0TVP0PdXnm
 * cj84RaDiiSk/cERlFzFJ5L8ULMwxdOtYwXwZ4upITw2lT+8zDlBD2i3zZ4TcWrzE
 * /su5Kpu+Mp3wthfGX+ZGga2T/NS8ZCKZE+gJDPKQZ/x34VBw+YANQGyCJPv1iMaE
 * RyagnpApH9OPSrRIp2iR6uWT6836CET2erbfPaC1odyd8IsbnLldVs9CklH7EgXL
 * Nms+DqrQEbNmvMuQYEFyZEHN9D1fGONeacx+cjI85FyMSHSEO65JJmasAxgQe4nF
 * /yVz3rNQ2qAGqBhjsjP/WaXuB2aLZiAli/HjN17EJws=
 * -----END RSA PRIVATE KEY-----
 *
 * -----BEGIN RSA PRIVATE KEY-----
 * MIIBOQIBAAJBALlfGg/5ZweJcW5zqLdnQ2uyircqDDlENKnv9FABOm/j0wnlPHqX
 * CCqFBLoM7tG8ohci1SPy6fLJ5dqLf5FOH2sCAwEAAQJATO0/hpOMgx8xmJGc2Yeb
 * /gyY7kwfyIAajs9Khw0LcDTYTo2EAI+vMmDpU+dvmOCLUqq/Z2tiKJhGyrmcBlxr
 * kQIhAPYkbYovtvWHslxRb78x4eCrn2p1H7iolNKbyepjCI3zAiEAwMufJlLI9Q0O
 * BIr7fPnUhbs9NyMHLIvIQAf/hXYubqkCIGJZR9NxIT+VyrSMbYQNoF0u9fGJfvU/
 * lsdYLCOVEnP1AiAsSFjUx50K1CXNG1MqYIPU963W1T/Xln+3XV7ue7esiQIgW2Lu
 * xGvz2dAUsGId+Xr2GZXb7ZucY/cPt4o5qdP1m7c=
 * -----END RSA PRIVATE KEY-----
 *
 * Private-Key: (512 bit)
 * modulus:
 *     00:b9:5f:1a:0f:f9:67:07:89:71:6e:73:a8:b7:67:
 *     43:6b:b2:8a:b7:2a:0c:39:44:34:a9:ef:f4:50:01:
 *     3a:6f:e3:d3:09:e5:3c:7a:97:08:2a:85:04:ba:0c:
 *     ee:d1:bc:a2:17:22:d5:23:f2:e9:f2:c9:e5:da:8b:
 *     7f:91:4e:1f:6b
 * publicExponent: 65537 (0x10001)
 * privateExponent:
 *     4c:ed:3f:86:93:8c:83:1f:31:98:91:9c:d9:87:9b:
 *     fe:0c:98:ee:4c:1f:c8:80:1a:8e:cf:4a:87:0d:0b:
 *     70:34:d8:4e:8d:84:00:8f:af:32:60:e9:53:e7:6f:
 *     98:e0:8b:52:aa:bf:67:6b:62:28:98:46:ca:b9:9c:
 *     06:5c:6b:91
 * prime1:
 *     00:f6:24:6d:8a:2f:b6:f5:87:b2:5c:51:6f:bf:31:
 *     e1:e0:ab:9f:6a:75:1f:b8:a8:94:d2:9b:c9:ea:63:
 *     08:8d:f3
 * prime2:
 *     00:c0:cb:9f:26:52:c8:f5:0d:0e:04:8a:fb:7c:f9:
 *     d4:85:bb:3d:37:23:07:2c:8b:c8:40:07:ff:85:76:
 *     2e:6e:a9
 * exponent1:
 *     62:59:47:d3:71:21:3f:95:ca:b4:8c:6d:84:0d:a0:
 *     5d:2e:f5:f1:89:7e:f5:3f:96:c7:58:2c:23:95:12:
 *     73:f5
 * exponent2:
 *     2c:48:58:d4:c7:9d:0a:d4:25:cd:1b:53:2a:60:83:
 *     d4:f7:ad:d6:d5:3f:d7:96:7f:b7:5d:5e:ee:7b:b7:
 *     ac:89
 * coefficient:
 *     5b:62:ee:c4:6b:f3:d9:d0:14:b0:62:1d:f9:7a:f6:
 *     19:95:db:ed:9b:9c:63:f7:0f:b7:8a:39:a9:d3:f5:
 *     9b:b7
 *
 *
 * server certificate:
 *  Data:
 *      Version: 3 (0x2)
 *      Serial Number: 11 (0xb)
 *      Signature Algorithm: sha1WithRSAEncryption
 *      Issuer: C=US, ST=Some-State, O=Some Org, CN=Someone
 *      Validity
 *          Not Before: Apr 18 15:07:30 2008 GMT
 *          Not After : Jan  4 15:07:30 2028 GMT
 *      Subject: C=US, ST=Some-State, O=Some Org, CN=SomeoneExport
 *      Subject Public Key Info:
 *          Public Key Algorithm: rsaEncryption
 *          RSA Public Key: (512 bit)
 *              Modulus (512 bit):
 *                  00:b9:5f:1a:0f:f9:67:07:89:71:6e:73:a8:b7:67:
 *                  43:6b:b2:8a:b7:2a:0c:39:44:34:a9:ef:f4:50:01:
 *                  3a:6f:e3:d3:09:e5:3c:7a:97:08:2a:85:04:ba:0c:
 *                  ee:d1:bc:a2:17:22:d5:23:f2:e9:f2:c9:e5:da:8b:
 *                  7f:91:4e:1f:6b
 *              Exponent: 65537 (0x10001)
 *      X509v3 extensions:
 *          X509v3 Basic Constraints:
 *              CA:FALSE
 *          X509v3 Key Usage:
 *              Digital Signature, Non Repudiation, Key Encipherment
 *          X509v3 Subject Key Identifier:
 *              F1:30:98:BE:7C:AA:F9:B1:91:38:60:AE:13:5F:67:9C:0A:32:9E:31
 *          X509v3 Authority Key Identifier:
 *              keyid:B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
 *
 * -----BEGIN CERTIFICATE-----
 * MIICIDCCAYmgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzET
 * MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT
 * B1NvbWVvbmUwHhcNMDgwNDE4MTUwNzMwWhcNMjgwMTA0MTUwNzMwWjBNMQswCQYD
 * VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx
 * FjAUBgNVBAMTDVNvbWVvbmVFeHBvcnQwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
 * uV8aD/lnB4lxbnOot2dDa7KKtyoMOUQ0qe/0UAE6b+PTCeU8epcIKoUEugzu0byi
 * FyLVI/Lp8snl2ot/kU4fawIDAQABo1owWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF
 * 4DAdBgNVHQ4EFgQU8TCYvnyq+bGROGCuE19nnAoynjEwHwYDVR0jBBgwFoAUtTJD
 * 1wAkkrrpleX5o2RshO4zLhUwDQYJKoZIhvcNAQEFBQADgYEAFU+fP9FSTQNVZOhv
 * eJ+zq6wI/biwzTgPbAq3yu2gb5kT85z4nzqBhPd2LWWFXhUW/D8QyNZ54X30y0Ug
 * 3NfUAvOANW7CgUbHBmm77KQiF4nWdh338qqq9HzLGrPqcxX0dmiq2RBVPy9wb2Ea
 * FTZiU2v+9pkoLoSDnCOfPCg/4Q4=
 * -----END CERTIFICATE-----
 *
 *
 * Trusted CA certificate:
 * Certificate:
 *   Data:
 *       Version: 3 (0x2)
 *       Serial Number: 0 (0x0)
 *       Signature Algorithm: md5WithRSAEncryption
 *       Issuer: C=US, ST=Some-State, O=Some Org, CN=Someone
 *       Validity
 *           Not Before: Mar 30 11:44:47 2001 GMT
 *           Not After : Apr 27 11:44:47 2028 GMT
 *       Subject: C=US, ST=Some-State, O=Some Org, CN=Someone
 *       Subject Public Key Info:
 *           Public Key Algorithm: rsaEncryption
 *           RSA Public Key: (1024 bit)
 *               Modulus (1024 bit):
 *                   00:c1:98:e4:7a:87:53:0f:94:87:dc:da:f3:59:39:
 *                   3e:36:95:e8:77:58:ff:46:8a:81:1b:5e:c5:4c:fa:
 *                   b6:91:19:30:be:5b:ef:4c:aa:84:30:a4:9a:d4:68:
 *                   af:ef:fa:b4:2c:76:8b:29:33:46:cf:38:74:7c:79:
 *                   d5:07:a6:43:39:84:52:39:4f:8a:1c:f3:73:19:12:
 *                   40:cf:ee:a1:77:43:01:02:be:8d:32:11:28:70:f4:
 *                   cf:ab:43:75:e4:fb:74:f1:8c:2e:43:24:ba:85:3f:
 *                   66:3a:05:ea:f7:ce:5b:97:e2:34:a3:f0:87:f4:f8:
 *                   d1:59:12:5a:68:b7:78:64:a9
 *               Exponent: 65537 (0x10001)
 *       X509v3 extensions:
 *           X509v3 Subject Key Identifier:
 *               B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
 *           X509v3 Authority Key Identifier:
 *               keyid:B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
 *               DirName:/C=US/ST=Some-State/O=Some Org/CN=Someone
 *               serial:00
 *
 *           X509v3 Basic Constraints:
 *               CA:TRUE
 *
 * -----BEGIN CERTIFICATE-----
 * MIICpjCCAg+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBHMQswCQYDVQQGEwJVUzET
 * MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT
 * B1NvbWVvbmUwHhcNMDEwMzMwMTE0NDQ3WhcNMjgwNDI3MTE0NDQ3WjBHMQswCQYD
 * VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx
 * EDAOBgNVBAMTB1NvbWVvbmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMGY
 * 5HqHUw+Uh9za81k5PjaV6HdY/0aKgRtexUz6tpEZML5b70yqhDCkmtRor+/6tCx2
 * iykzRs84dHx51QemQzmEUjlPihzzcxkSQM/uoXdDAQK+jTIRKHD0z6tDdeT7dPGM
 * LkMkuoU/ZjoF6vfOW5fiNKPwh/T40VkSWmi3eGSpAgMBAAGjgaEwgZ4wHQYDVR0O
 * BBYEFLUyQ9cAJJK66ZXl+aNkbITuMy4VMG8GA1UdIwRoMGaAFLUyQ9cAJJK66ZXl
 * +aNkbITuMy4VoUukSTBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0
 * ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMTB1NvbWVvbmWCAQAwDAYDVR0T
 * BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBhf3PX0xWxtaUwZlWCO7GfPwCKgBWr
 * CXqlqjtWHCshaaU7wUsDOwxFDWwKjFrMerQLsLuBlhdXEbNfSPjychkQtfezQHcS
 * q0Atq7+KVSmRbDw6oKVRs5v1BBzLCupy+o16fNz3/hwreAWwQnSMtAh/osNS9w1b
 * QeVWU+JV47H+vg==
 * -----END CERTIFICATE-----
 *
 */

import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.net.ssl.*;
import java.math.BigInteger;

public class RSAExport {

    /*
     * =============================================================
     * Set the various variables needed for the tests, then
     * specify what tests to run on each side.
     */


    /*
     * Should we run the client or server in a separate thread?
     * Both sides can throw exceptions, but do you have a preference
     * as to which side should be the main thread.
     */
    static boolean separateServerThread = true;

    /*
     * Where do we find the keystores?
     */
    static String trusedCertStr =
        "-----BEGIN CERTIFICATE-----\n" +
        "MIICpjCCAg+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBHMQswCQYDVQQGEwJVUzET\n" +
        "MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT\n" +
        "B1NvbWVvbmUwHhcNMDEwMzMwMTE0NDQ3WhcNMjgwNDI3MTE0NDQ3WjBHMQswCQYD\n" +
        "VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx\n" +
        "EDAOBgNVBAMTB1NvbWVvbmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMGY\n" +
        "5HqHUw+Uh9za81k5PjaV6HdY/0aKgRtexUz6tpEZML5b70yqhDCkmtRor+/6tCx2\n" +
        "iykzRs84dHx51QemQzmEUjlPihzzcxkSQM/uoXdDAQK+jTIRKHD0z6tDdeT7dPGM\n" +
        "LkMkuoU/ZjoF6vfOW5fiNKPwh/T40VkSWmi3eGSpAgMBAAGjgaEwgZ4wHQYDVR0O\n" +
        "BBYEFLUyQ9cAJJK66ZXl+aNkbITuMy4VMG8GA1UdIwRoMGaAFLUyQ9cAJJK66ZXl\n" +
        "+aNkbITuMy4VoUukSTBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0\n" +
        "ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMTB1NvbWVvbmWCAQAwDAYDVR0T\n" +
        "BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBhf3PX0xWxtaUwZlWCO7GfPwCKgBWr\n" +
        "CXqlqjtWHCshaaU7wUsDOwxFDWwKjFrMerQLsLuBlhdXEbNfSPjychkQtfezQHcS\n" +
        "q0Atq7+KVSmRbDw6oKVRs5v1BBzLCupy+o16fNz3/hwreAWwQnSMtAh/osNS9w1b\n" +
        "QeVWU+JV47H+vg==\n" +
        "-----END CERTIFICATE-----";

    static String serverCertStr =
        "-----BEGIN CERTIFICATE-----\n" +
        "MIICIDCCAYmgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzET\n" +
        "MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT\n" +
        "B1NvbWVvbmUwHhcNMDgwNDE4MTUwNzMwWhcNMjgwMTA0MTUwNzMwWjBNMQswCQYD\n" +
        "VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx\n" +
        "FjAUBgNVBAMTDVNvbWVvbmVFeHBvcnQwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA\n" +
        "uV8aD/lnB4lxbnOot2dDa7KKtyoMOUQ0qe/0UAE6b+PTCeU8epcIKoUEugzu0byi\n" +
        "FyLVI/Lp8snl2ot/kU4fawIDAQABo1owWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF\n" +
        "4DAdBgNVHQ4EFgQU8TCYvnyq+bGROGCuE19nnAoynjEwHwYDVR0jBBgwFoAUtTJD\n" +
        "1wAkkrrpleX5o2RshO4zLhUwDQYJKoZIhvcNAQEFBQADgYEAFU+fP9FSTQNVZOhv\n" +
        "eJ+zq6wI/biwzTgPbAq3yu2gb5kT85z4nzqBhPd2LWWFXhUW/D8QyNZ54X30y0Ug\n" +
        "3NfUAvOANW7CgUbHBmm77KQiF4nWdh338qqq9HzLGrPqcxX0dmiq2RBVPy9wb2Ea\n" +
        "FTZiU2v+9pkoLoSDnCOfPCg/4Q4=\n" +
        "-----END CERTIFICATE-----";

    static byte privateExponent[] = {
        (byte)0x4c, (byte)0xed, (byte)0x3f, (byte)0x86,
        (byte)0x93, (byte)0x8c, (byte)0x83, (byte)0x1f,
        (byte)0x31, (byte)0x98, (byte)0x91, (byte)0x9c,
        (byte)0xd9, (byte)0x87, (byte)0x9b, (byte)0xfe,
        (byte)0x0c, (byte)0x98, (byte)0xee, (byte)0x4c,
        (byte)0x1f, (byte)0xc8, (byte)0x80, (byte)0x1a,
        (byte)0x8e, (byte)0xcf, (byte)0x4a, (byte)0x87,
        (byte)0x0d, (byte)0x0b, (byte)0x70, (byte)0x34,
        (byte)0xd8, (byte)0x4e, (byte)0x8d, (byte)0x84,
        (byte)0x00, (byte)0x8f, (byte)0xaf, (byte)0x32,
        (byte)0x60, (byte)0xe9, (byte)0x53, (byte)0xe7,
        (byte)0x6f, (byte)0x98, (byte)0xe0, (byte)0x8b,
        (byte)0x52, (byte)0xaa, (byte)0xbf, (byte)0x67,
        (byte)0x6b, (byte)0x62, (byte)0x28, (byte)0x98,
        (byte)0x46, (byte)0xca, (byte)0xb9, (byte)0x9c,
        (byte)0x06, (byte)0x5c, (byte)0x6b, (byte)0x91
    };

    static byte modulus[] = {
        (byte)0x00,
        (byte)0xb9, (byte)0x5f, (byte)0x1a, (byte)0x0f,
        (byte)0xf9, (byte)0x67, (byte)0x07, (byte)0x89,
        (byte)0x71, (byte)0x6e, (byte)0x73, (byte)0xa8,
        (byte)0xb7, (byte)0x67, (byte)0x43, (byte)0x6b,
        (byte)0xb2, (byte)0x8a, (byte)0xb7, (byte)0x2a,
        (byte)0x0c, (byte)0x39, (byte)0x44, (byte)0x34,
        (byte)0xa9, (byte)0xef, (byte)0xf4, (byte)0x50,
        (byte)0x01, (byte)0x3a, (byte)0x6f, (byte)0xe3,
        (byte)0xd3, (byte)0x09, (byte)0xe5, (byte)0x3c,
        (byte)0x7a, (byte)0x97, (byte)0x08, (byte)0x2a,
        (byte)0x85, (byte)0x04, (byte)0xba, (byte)0x0c,
        (byte)0xee, (byte)0xd1, (byte)0xbc, (byte)0xa2,
        (byte)0x17, (byte)0x22, (byte)0xd5, (byte)0x23,
        (byte)0xf2, (byte)0xe9, (byte)0xf2, (byte)0xc9,
        (byte)0xe5, (byte)0xda, (byte)0x8b, (byte)0x7f,
        (byte)0x91, (byte)0x4e, (byte)0x1f, (byte)0x6b
    };

    static char passphrase[] = "passphrase".toCharArray();

    /*
     * Is the server ready to serve?
     */
    volatile static boolean serverReady = false;

    /*
     * Turn on SSL debugging?
     */
    static boolean debug = false;

    /*
     * If the client or server is doing some kind of object creation
     * that the other side depends on, and that thread prematurely
     * exits, you may experience a hang.  The test harness will
     * terminate all hung threads after its timeout has expired,
     * currently 3 minutes by default, but you might try to be
     * smart about it....
     */

    /*
     * Define the server side of the test.
     *
     * If the server prematurely exits, serverReady will be set to true
     * to avoid infinite hangs.
     */
    void doServerSide() throws Exception {
        SSLServerSocketFactory sslssf =
                getSSLContext(true).getServerSocketFactory();
        SSLServerSocket sslServerSocket =
                (SSLServerSocket) sslssf.createServerSocket(serverPort);

        serverPort = sslServerSocket.getLocalPort();

        /*
         * Signal Client, we're ready for this connect.
         */
        serverReady = true;

        // Enable RSA_EXPORT cipher suites only.
        try {
            String enabledSuites[] = {
                "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"};
            sslServerSocket.setEnabledCipherSuites(enabledSuites);
        } catch (IllegalArgumentException iae) {
            // ignore the exception a cipher suite is unsupported.
        }

        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();

        sslIS.read();
        sslOS.write(85);
        sslOS.flush();


        sslSocket.close();
    }

    /*
     * Define the client side of the test.
     *
     * If the server prematurely exits, serverReady will be set to true
     * to avoid infinite hangs.
     */
    void doClientSide() throws Exception {

        /*
         * Wait for server to get started.
         */
        while (!serverReady) {
            Thread.sleep(50);
        }

        SSLSocketFactory sslsf =
                getSSLContext(false).getSocketFactory();
        SSLSocket sslSocket = (SSLSocket)
                sslsf.createSocket("localhost", serverPort);

        // Enable RSA_EXPORT cipher suites only.
        try {
            String enabledSuites[] = {
                "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"};
            sslSocket.setEnabledCipherSuites(enabledSuites);
        } catch (IllegalArgumentException iae) {
            // ignore the exception a cipher suite is unsupported.
        }

        InputStream sslIS = sslSocket.getInputStream();
        OutputStream sslOS = sslSocket.getOutputStream();

        sslOS.write(280);
        sslOS.flush();
        sslIS.read();

        sslSocket.close();
    }

    /*
     * =============================================================
     * The remainder is just support stuff
     */

    // use any free port by default
    volatile int serverPort = 0;

    volatile Exception serverException = null;
    volatile Exception clientException = null;

    public static void main(String[] args) throws Exception {
        if (debug)
            System.setProperty("javax.net.debug", "all");

        /*
         * Start the tests.
         */
        new RSAExport();
    }

    Thread clientThread = null;
    Thread serverThread = null;

    /*
     * Primary constructor, used to drive remainder of the test.
     *
     * Fork off the other side, then do your work.
     */
    RSAExport() throws Exception {
        if (separateServerThread) {
            startServer(true);
            startClient(false);
        } else {
            startClient(true);
            startServer(false);
        }

        /*
         * Wait for other side to close down.
         */
        if (separateServerThread) {
            serverThread.join();
        } else {
            clientThread.join();
        }

        /*
         * When we get here, the test is pretty much over.
         *
         * If the main thread excepted, that propagates back
         * immediately.  If the other thread threw an exception, we
         * should report back.
         */
        if (serverException != null)
            throw serverException;
        if (clientException != null)
            throw clientException;
    }

    void startServer(boolean newThread) throws Exception {
        if (newThread) {
            serverThread = new Thread() {
                public void run() {
                    try {
                        doServerSide();
                    } catch (Exception e) {
                        /*
                         * Our server thread just died.
                         *
                         * Release the client, if not active already...
                         */
                        System.err.println("Server died..." + e);
                        serverReady = true;
                        serverException = e;
                    }
                }
            };
            serverThread.start();
        } else {
            doServerSide();
        }
    }

    void startClient(boolean newThread) throws Exception {
        if (newThread) {
            clientThread = new Thread() {
                public void run() {
                    try {
                        doClientSide();
                    } catch (Exception e) {
                        /*
                         * Our client thread just died.
                         */
                        System.err.println("Client died...");
                        clientException = e;
                    }
                }
            };
            clientThread.start();
        } else {
            doClientSide();
        }
    }

    // Get the SSL context
    private SSLContext getSSLContext(boolean authnRequired) throws Exception {
        // generate certificate from cert string
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        ByteArrayInputStream is =
                    new ByteArrayInputStream(trusedCertStr.getBytes());
        Certificate trustedCert = cf.generateCertificate(is);

        // create a key store
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(null, null);

        // import the trusted cert
        ks.setCertificateEntry("RSA Export Signer", trustedCert);

        if (authnRequired) {
            // generate the private key.
            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
                                            new BigInteger(modulus),
                                            new BigInteger(privateExponent));
            KeyFactory kf = KeyFactory.getInstance("RSA");
            RSAPrivateKey priKey =
                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);

            // generate certificate chain
            is = new ByteArrayInputStream(serverCertStr.getBytes());
            Certificate serverCert = cf.generateCertificate(is);

            Certificate[] chain = new Certificate[2];
            chain[0] = serverCert;
            chain[1] = trustedCert;

            // import the key entry.
            ks.setKeyEntry("RSA Export", priKey, passphrase, chain);
        }

        // create SSL context
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
        tmf.init(ks);

        SSLContext ctx = SSLContext.getInstance("TLS");
        if (authnRequired) {
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, passphrase);

            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        } else {
            ctx.init(null, tmf.getTrustManagers(), null);
        }

        return ctx;
    }

}
