1/*
2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26//
27// SunJSSE does not support dynamic system properties, no way to re-use
28// system properties in samevm/agentvm mode.
29//
30
31/*
32 * @test
33 * @bug 7030966
34 * @summary Support AEAD CipherSuites
35 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
36 * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_128_GCM_SHA256
37 * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
38 * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_128_GCM_SHA256
39 */
40
41/*
42 * Need additional key materials to run the following cases.
43 *
44 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
45 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
46 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
47 *
48 * Need unlimited JCE Unlimited Strength Jurisdiction Policy to run the
49 * following cases.
50 *
51 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
52 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
53 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
54 * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
55 * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_256_GCM_SHA384
56 * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
57 * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_256_GCM_SHA384
58 */
59
60import java.net.*;
61import java.util.*;
62import java.io.*;
63import javax.net.ssl.*;
64import java.security.Security;
65import java.security.KeyStore;
66import java.security.KeyFactory;
67import java.security.cert.Certificate;
68import java.security.cert.CertificateFactory;
69import java.security.spec.*;
70import java.security.interfaces.*;
71
72
73public class ShortRSAKeyGCM {
74
75    /*
76     * =============================================================
77     * Set the various variables needed for the tests, then
78     * specify what tests to run on each side.
79     */
80
81    /*
82     * Should we run the client or server in a separate thread?
83     * Both sides can throw exceptions, but do you have a preference
84     * as to which side should be the main thread.
85     */
86    static boolean separateServerThread = true;
87
88    /*
89     * Where do we find the keystores?
90     */
91    // Certificates and key used in the test.
92    static String trustedCertStr =
93        "-----BEGIN CERTIFICATE-----\n" +
94        "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
95        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
96        "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
97        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
98        "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" +
99        "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" +
100        "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" +
101        "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" +
102        "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" +
103        "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
104        "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
105        "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" +
106        "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" +
107        "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" +
108        "-----END CERTIFICATE-----";
109
110    static String targetCertStr =
111        "-----BEGIN CERTIFICATE-----\n" +
112        "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
113        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
114        "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
115        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
116        "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" +
117        "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" +
118        "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" +
119        "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" +
120        "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" +
121        "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" +
122        "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" +
123        "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" +
124        "-----END CERTIFICATE-----";
125
126    // Private key in the format of PKCS#8, key size is 512 bits.
127    static String targetPrivateKey =
128        "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" +
129        "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" +
130        "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" +
131        "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" +
132        "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" +
133        "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" +
134        "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" +
135        "3fnqsTgaUs4=";
136
137    static char passphrase[] = "passphrase".toCharArray();
138
139    /*
140     * Is the server ready to serve?
141     */
142    volatile static boolean serverReady = false;
143
144    /*
145     * Turn on SSL debugging?
146     */
147    static boolean debug = false;
148
149    /*
150     * Define the server side of the test.
151     *
152     * If the server prematurely exits, serverReady will be set to true
153     * to avoid infinite hangs.
154     */
155    void doServerSide() throws Exception {
156        SSLContext context = generateSSLContext(null, targetCertStr,
157                                            targetPrivateKey);
158        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
159        SSLServerSocket sslServerSocket =
160            (SSLServerSocket)sslssf.createServerSocket(serverPort);
161        serverPort = sslServerSocket.getLocalPort();
162
163        /*
164         * Signal Client, we're ready for his connect.
165         */
166        serverReady = true;
167
168        SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
169        sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
170        InputStream sslIS = sslSocket.getInputStream();
171        OutputStream sslOS = sslSocket.getOutputStream();
172
173        sslIS.read();
174        sslOS.write('A');
175        sslOS.flush();
176
177        sslSocket.close();
178    }
179
180    /*
181     * Define the client side of the test.
182     *
183     * If the server prematurely exits, serverReady will be set to true
184     * to avoid infinite hangs.
185     */
186    void doClientSide() throws Exception {
187
188        /*
189         * Wait for server to get started.
190         */
191        while (!serverReady) {
192            Thread.sleep(50);
193        }
194
195        SSLContext context = generateSSLContext(trustedCertStr, null, null);
196        SSLSocketFactory sslsf = context.getSocketFactory();
197
198        SSLSocket sslSocket =
199            (SSLSocket)sslsf.createSocket("localhost", serverPort);
200
201        // enable TLSv1.2 only
202        sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
203
204        // enable a block cipher
205        sslSocket.setEnabledCipherSuites(new String[] {cipherSuite});
206
207        InputStream sslIS = sslSocket.getInputStream();
208        OutputStream sslOS = sslSocket.getOutputStream();
209
210        sslOS.write('B');
211        sslOS.flush();
212        sslIS.read();
213
214        sslSocket.close();
215    }
216
217    /*
218     * =============================================================
219     * The remainder is just support stuff
220     */
221    private static String tmAlgorithm;        // trust manager
222    private static String cipherSuite;        // cipher suite
223
224    private static void parseArguments(String[] args) {
225        tmAlgorithm = args[0];
226        cipherSuite = args[1];
227    }
228
229    private static SSLContext generateSSLContext(String trustedCertStr,
230            String keyCertStr, String keySpecStr) throws Exception {
231
232        // generate certificate from cert string
233        CertificateFactory cf = CertificateFactory.getInstance("X.509");
234
235        // create a key store
236        KeyStore ks = KeyStore.getInstance("JKS");
237        ks.load(null, null);
238
239        // import the trused cert
240        Certificate trusedCert = null;
241        ByteArrayInputStream is = null;
242        if (trustedCertStr != null) {
243            is = new ByteArrayInputStream(trustedCertStr.getBytes());
244            trusedCert = cf.generateCertificate(is);
245            is.close();
246
247            ks.setCertificateEntry("RSA Export Signer", trusedCert);
248        }
249
250        if (keyCertStr != null) {
251            // generate the private key.
252            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
253                                Base64.getMimeDecoder().decode(keySpecStr));
254            KeyFactory kf = KeyFactory.getInstance("RSA");
255            RSAPrivateKey priKey =
256                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
257
258            // generate certificate chain
259            is = new ByteArrayInputStream(keyCertStr.getBytes());
260            Certificate keyCert = cf.generateCertificate(is);
261            is.close();
262
263            Certificate[] chain = null;
264            if (trusedCert != null) {
265                chain = new Certificate[2];
266                chain[0] = keyCert;
267                chain[1] = trusedCert;
268            } else {
269                chain = new Certificate[1];
270                chain[0] = keyCert;
271            }
272
273            // import the key entry.
274            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
275        }
276
277        // create SSL context
278        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
279        tmf.init(ks);
280
281        SSLContext ctx = SSLContext.getInstance("TLS");
282        if (keyCertStr != null && !keyCertStr.isEmpty()) {
283            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
284            kmf.init(ks, passphrase);
285
286            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
287            ks = null;
288        } else {
289            ctx.init(null, tmf.getTrustManagers(), null);
290        }
291
292        return ctx;
293    }
294
295
296    // use any free port by default
297    volatile int serverPort = 0;
298
299    volatile Exception serverException = null;
300    volatile Exception clientException = null;
301
302    public static void main(String[] args) throws Exception {
303        // reset the security property to make sure that the algorithms
304        // and keys used in this test are not disabled.
305        Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2");
306        Security.setProperty("jdk.tls.disabledAlgorithms",
307                "SSLv3, RC4, DH keySize < 768");
308
309        if (debug) {
310            System.setProperty("javax.net.debug", "all");
311        }
312
313        /*
314         * Get the customized arguments.
315         */
316        parseArguments(args);
317
318        /*
319         * Start the tests.
320         */
321        new ShortRSAKeyGCM();
322    }
323
324    Thread clientThread = null;
325    Thread serverThread = null;
326
327    /*
328     * Primary constructor, used to drive remainder of the test.
329     *
330     * Fork off the other side, then do your work.
331     */
332    ShortRSAKeyGCM() throws Exception {
333        try {
334            if (separateServerThread) {
335                startServer(true);
336                startClient(false);
337            } else {
338                startClient(true);
339                startServer(false);
340            }
341        } catch (Exception e) {
342            // swallow for now.  Show later
343        }
344
345        /*
346         * Wait for other side to close down.
347         */
348        if (separateServerThread) {
349            serverThread.join();
350        } else {
351            clientThread.join();
352        }
353
354        /*
355         * When we get here, the test is pretty much over.
356         * Which side threw the error?
357         */
358        Exception local;
359        Exception remote;
360        String whichRemote;
361
362        if (separateServerThread) {
363            remote = serverException;
364            local = clientException;
365            whichRemote = "server";
366        } else {
367            remote = clientException;
368            local = serverException;
369            whichRemote = "client";
370        }
371
372        /*
373         * If both failed, return the curthread's exception, but also
374         * print the remote side Exception
375         */
376        if ((local != null) && (remote != null)) {
377            System.out.println(whichRemote + " also threw:");
378            remote.printStackTrace();
379            System.out.println();
380            throw local;
381        }
382
383        if (remote != null) {
384            throw remote;
385        }
386
387        if (local != null) {
388            throw local;
389        }
390    }
391
392    void startServer(boolean newThread) throws Exception {
393        if (newThread) {
394            serverThread = new Thread() {
395                public void run() {
396                    try {
397                        doServerSide();
398                    } catch (Exception e) {
399                        /*
400                         * Our server thread just died.
401                         *
402                         * Release the client, if not active already...
403                         */
404                        System.err.println("Server died..." + e);
405                        serverReady = true;
406                        serverException = e;
407                    }
408                }
409            };
410            serverThread.start();
411        } else {
412            try {
413                doServerSide();
414            } catch (Exception e) {
415                serverException = e;
416            } finally {
417                serverReady = true;
418            }
419        }
420    }
421
422    void startClient(boolean newThread) throws Exception {
423        if (newThread) {
424            clientThread = new Thread() {
425                public void run() {
426                    try {
427                        doClientSide();
428                    } catch (Exception e) {
429                        /*
430                         * Our client thread just died.
431                         */
432                        System.err.println("Client died..." + e);
433                        clientException = e;
434                    }
435                }
436            };
437            clientThread.start();
438        } else {
439            try {
440                doClientSide();
441            } catch (Exception e) {
442                clientException = e;
443            }
444        }
445    }
446}
447