SSLSessionTest.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package tests.api.javax.net.ssl;
19
20import dalvik.annotation.AndroidOnly;
21import dalvik.annotation.KnownFailure;
22import dalvik.annotation.TestLevel;
23import dalvik.annotation.TestTargetClass;
24import dalvik.annotation.TestTargetNew;
25import dalvik.annotation.TestTargets;
26
27import junit.framework.TestCase;
28
29import org.apache.harmony.luni.util.Base64;
30
31import tests.api.javax.net.ssl.HandshakeCompletedEventTest.MyHandshakeListener;
32import tests.api.javax.net.ssl.HandshakeCompletedEventTest.TestTrustManager;
33import tests.support.Support_PortManager;
34
35import java.io.ByteArrayInputStream;
36import java.io.InputStream;
37import java.io.OutputStream;
38import java.net.InetAddress;
39import java.net.InetSocketAddress;
40import java.security.KeyStore;
41import java.security.Principal;
42import java.security.cert.Certificate;
43import java.util.Date;
44
45import javax.net.ssl.KeyManager;
46import javax.net.ssl.KeyManagerFactory;
47import javax.net.ssl.SSLContext;
48import javax.net.ssl.SSLPeerUnverifiedException;
49import javax.net.ssl.SSLServerSocket;
50import javax.net.ssl.SSLSession;
51import javax.net.ssl.SSLSocket;
52import javax.net.ssl.SSLSessionBindingEvent;
53import javax.net.ssl.SSLSessionBindingListener;
54import javax.net.ssl.TrustManager;
55import javax.security.cert.X509Certificate;
56
57/**
58 * Tests for SSLSession class
59 *
60 */
61@TestTargetClass(SSLSession.class)
62public class SSLSessionTest extends TestCase {
63
64    // set to true if on Android, false if on RI
65    boolean useBKS = true;
66
67    /**
68     * @tests javax.net.ssl.SSLSession#getPeerHost()
69     * @tests javax.net.ssl.SSLSession#getPeerPort()
70     */
71    @TestTargets({
72        @TestTargetNew(
73            level = TestLevel.COMPLETE,
74            notes = "",
75            method = "getPeerHost",
76            args = {}
77        ),
78        @TestTargetNew(
79            level = TestLevel.COMPLETE,
80            notes = "",
81            method = "getPeerPort",
82            args = {}
83        )
84    })
85    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
86    public void test_getPeerHost() {
87        SSLSession s = clientSession;
88        try {
89            assertEquals(s.getPeerHost(), InetAddress.getLocalHost().getHostName());
90            assertEquals(s.getPeerPort(), port);
91        } catch (Exception ex) {
92            fail("Unexpected exception " + ex);
93        }
94    }
95
96    /**
97     * @tests javax.net.ssl.SSLSession#invalidate()
98     * @tests javax.net.ssl.SSLSession#isValid()
99     */
100    @TestTargets({
101        @TestTargetNew(
102            level = TestLevel.COMPLETE,
103            notes = "",
104            method = "invalidate",
105            args = {}
106        ),
107        @TestTargetNew(
108            level = TestLevel.COMPLETE,
109            notes = "",
110            method = "isValid",
111            args = {}
112        )
113    })
114    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
115    public void test_invalidate() {
116        SSLSession s = clientSession;
117        try {
118            assertTrue(s.isValid());
119            s.invalidate();
120            assertFalse(s.isValid());
121        } catch (Exception ex) {
122            fail("Unexpected exception " + ex);
123        }
124    }
125
126    /**
127     * @tests javax.net.ssl.SSLSession#getPeerPrincipal()
128     */
129    @TestTargetNew(
130        level = TestLevel.SUFFICIENT,
131        notes = "Exception wasn't implemented in the interface's class",
132        method = "getPeerPrincipal",
133        args = {}
134    )
135    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
136    public void test_getPeerPrincipal() {
137        try {
138            Principal p1 = clientSession.getPeerPrincipal();
139            KeyStore store = server.getStore();
140            Certificate cert = store.getCertificate("mykey");
141            X509Certificate c = X509Certificate.getInstance(cert.getEncoded());
142            Principal p2 = c.getSubjectDN();
143            String name2 = p2.getName().replaceAll(" ", "");
144            String name1 = p1.getName().replaceAll(" ", "");
145            assertEquals(name2, name1);
146        } catch (Exception ex) {
147            fail("Unexpected exception " + ex);
148        }
149    }
150
151    /**
152     * @tests javax.net.ssl.SSLSession#getApplicationBufferSize()
153     */
154    @TestTargetNew(
155        level = TestLevel.COMPLETE,
156        notes = "",
157        method = "getApplicationBufferSize",
158        args = {}
159    )
160    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
161    public void test_getApplicationBufferSize() {
162        try {
163            assertTrue(clientSession.getApplicationBufferSize() > 0);
164        } catch (Exception ex) {
165            fail("Unexpected exception " + ex);
166        }
167    }
168
169    /**
170     * @tests javax.net.ssl.SSLSession#getCipherSuite()
171     */
172    @TestTargetNew(
173        level = TestLevel.COMPLETE,
174        notes = "",
175        method = "getCipherSuite",
176        args = {}
177    )
178    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
179    public void test_getCipherSuite() {
180        try {
181            assertEquals(cipherSuite, clientSession.getCipherSuite());
182        } catch (Exception ex) {
183            fail("Unexpected exception " + ex);
184        }
185    }
186
187    /**
188     * @tests javax.net.ssl.SSLSession#getCreationTime()
189     */
190    @TestTargetNew(
191        level = TestLevel.COMPLETE,
192        notes = "",
193        method = "getCreationTime",
194        args = {}
195    )
196    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
197    public void test_getCreationTime() {
198        try {
199            // check if creation time was in the last 10 seconds
200            long currentTime = System.currentTimeMillis();
201            long sessionTime = clientSession.getCreationTime();
202            long diff = currentTime - sessionTime;
203            assertTrue("diff between " + currentTime + " and " + sessionTime + " should be < 10000", diff < 10000);
204        } catch (Exception ex) {
205            fail("Unexpected exception " + ex);
206        }
207    }
208
209    /**
210     * @tests javax.net.ssl.SSLSession#getId()
211     */
212    @TestTargetNew(
213        level = TestLevel.COMPLETE,
214        notes = "",
215        method = "getId",
216        args = {}
217    )
218    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
219    public void test_getId() {
220        byte[] id = clientSession.getId();
221        try {
222            SSLSession sess =
223                clientSslContext.getClientSessionContext().getSession(id);
224            assertNotNull("Could not find session for id " + id, sess);
225            assertEquals(clientSession, sess);
226        } catch (Exception ex) {
227            fail("Unexpected exception " + ex);
228        }
229    }
230
231    /**
232     * @tests javax.net.ssl.SSLSession#getLastAccessedTime()
233     */
234    @TestTargetNew(
235        level = TestLevel.COMPLETE,
236        notes = "",
237        method = "getLastAccessedTime",
238        args = {}
239    )
240    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
241    public void test_getLastAccessedTime() {
242        try {
243            // check if last access time was in the last 10 seconds
244            long currentTime = System.currentTimeMillis();
245            long sessionTime = clientSession.getLastAccessedTime();
246            long diff = currentTime - sessionTime;
247            assertTrue("diff between " + currentTime + " and " + sessionTime + " should be < 10000", diff < 10000);
248            assertTrue ("diff should be < 10000 but is " + diff, diff < 10000);
249        } catch (Exception ex) {
250            fail("Unexpected exception " + ex);
251        }
252    }
253
254    /**
255     * @tests javax.net.ssl.SSLSession#getLocalCertificates()
256     */
257    @TestTargetNew(
258        level = TestLevel.COMPLETE,
259        notes = "",
260        method = "getLocalCertificates",
261        args = {}
262    )
263    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
264    public void test_getLocalCertificates() {
265        try {
266            KeyStore store = client.getStore();
267            Certificate cert = store.getCertificate("mykey");
268            Certificate[] certs = clientSession.getLocalCertificates();
269            assertEquals(cert, certs[0]);
270        } catch (Exception ex) {
271            fail("Unexpected exception " + ex);
272        }
273    }
274
275    /**
276     * @tests javax.net.ssl.SSLSession#getLocalPrincipal()
277     */
278    @TestTargetNew(
279        level = TestLevel.COMPLETE,
280        notes = "",
281        method = "getLocalPrincipal",
282        args = {}
283    )
284    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
285    public void test_getLocalPrincipal() {
286        try {
287            Principal p1 = clientSession.getLocalPrincipal();
288            KeyStore store = client.getStore();
289            Certificate cert = store.getCertificate("mykey");
290            X509Certificate c = X509Certificate.getInstance(cert.getEncoded());
291            Principal p2 = c.getSubjectDN();
292            String name2 = p2.getName().replaceAll(" ", "");
293            String name1 = p1.getName().replaceAll(" ", "");
294            assertEquals(name2, name1);
295        } catch (Exception ex) {
296            fail("Unexpected exception " + ex);
297        }
298    }
299
300    /**
301     * @tests javax.net.ssl.SSLSession#getPacketBufferSize()
302     */
303    @TestTargetNew(
304        level = TestLevel.COMPLETE,
305        notes = "",
306        method = "getPacketBufferSize",
307        args = {}
308    )
309    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
310    public void test_getPacketBufferSize() {
311        try {
312            assertTrue(clientSession.getPacketBufferSize() > 0);
313        } catch (Exception ex) {
314            fail("Unexpected exception " + ex);
315        }
316    }
317
318    /**
319     * @tests javax.net.ssl.SSLSession#getPeerCertificates()
320     */
321    @TestTargetNew(
322        level = TestLevel.SUFFICIENT,
323        notes = "",
324        method = "getPeerCertificates",
325        args = {}
326    )
327    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
328    public void test_getPeerCertificates() {
329//        try {
330//            Certificate[] res = clientSession.getPeerCertificates();
331//            fail("SSLPeerUnverifiedException wasn't thrown");
332//        } catch (SSLPeerUnverifiedException pue) {
333//            //expected
334//        }
335        try {
336            Certificate[] res = clientSession.getPeerCertificates();
337            assertTrue(res.length > 0);
338        } catch (Exception e) {
339            fail("Unexpected exception: " + e);
340        }
341    }
342
343    /**
344     * @tests javax.net.ssl.SSLSession#getPeerCertificateChain()
345     */
346    @TestTargetNew(
347        level = TestLevel.SUFFICIENT,
348        notes = "",
349        method = "getPeerCertificateChain",
350        args = {}
351    )
352    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
353    public void test_getPeerCertificateChain() {
354//        try {
355//            X509Certificate[] resN = clientSession.getPeerCertificateChain();
356//            fail("SSLPeerUnverifiedException wasn't thrown");
357//        } catch (SSLPeerUnverifiedException pue) {
358//            //expected
359//        }
360        try {
361            X509Certificate[] res = clientSession.getPeerCertificateChain();
362            assertTrue(res.length > 0);
363        } catch (Exception e) {
364            fail("Unexpected exception: " + e);
365        }
366    }
367
368    /**
369     * @tests javax.net.ssl.SSLSession#getProtocol()
370     */
371    @TestTargetNew(
372        level = TestLevel.COMPLETE,
373        notes = "",
374        method = "getProtocol",
375        args = {}
376    )
377    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
378    public void test_getProtocol() {
379        try {
380            assertEquals(clientSession.getProtocol(), "TLSv1");
381        } catch (Exception e) {
382            fail("Unexpected exception: " + e);
383        }
384    }
385
386    /**
387     * @tests javax.net.ssl.SSLSession#getSessionContext()
388     */
389    @TestTargetNew(
390        level = TestLevel.COMPLETE,
391        notes = "",
392        method = "getSessionContext",
393        args = {}
394    )
395    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
396    public void test_getSessionContext() {
397        try {
398            assertEquals(clientSslContext.getClientSessionContext(),
399                    clientSession.getSessionContext());
400        } catch (Exception e) {
401            fail("Unexpected exception: " + e);
402        }
403    }
404
405    /**
406     * @tests javax.net.ssl.SSLSession#putValue(String name, Object value)
407     * @tests javax.net.ssl.SSLSession#removeValue(String name)
408     * @tests javax.net.ssl.SSLSession#getValueNames()
409     */
410    @TestTargets({
411        @TestTargetNew(
412            level = TestLevel.COMPLETE,
413            notes = "",
414            method = "putValue",
415            args = {String.class, Object.class}
416        ),
417        @TestTargetNew(
418            level = TestLevel.COMPLETE,
419            notes = "",
420            method = "removeValue",
421            args = {String.class}
422        ),
423        @TestTargetNew(
424            level = TestLevel.COMPLETE,
425            notes = "",
426            method = "getValueNames",
427            args = {}
428        )
429    })
430    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
431    public void test_putValue() {
432        SSLSession s = clientSession;
433        mySSLSessionBindingListener sbl = new mySSLSessionBindingListener();
434        try {
435            assertNotNull(s.getValueNames());
436            assertEquals(s.getValueNames().length, 0);
437            s.putValue("Name_01", sbl);
438            s.putValue("Name_02", sbl);
439            s.putValue("Name_03", sbl);
440            assertEquals(s.getValueNames().length, 3);
441            s.removeValue("Name_01");
442            assertEquals(s.getValueNames().length, 2);
443        } catch (Exception e) {
444            fail("Unexpected exception: " + e);
445        }
446
447        try {
448            s.putValue(null, null);
449            fail("IllegalArgumentException wasn't thrown");
450        } catch (IllegalArgumentException iae) {
451            //expected
452        }
453        try {
454            s.putValue("ABC", null);
455            fail("IllegalArgumentException wasn't thrown");
456        } catch (IllegalArgumentException iae) {
457            //expected
458        }
459        try {
460            s.putValue(null, sbl);
461            fail("IllegalArgumentException wasn't thrown");
462        } catch (IllegalArgumentException iae) {
463            //expected
464        }
465
466        try {
467            s.removeValue(null);
468            fail("IllegalArgumentException wasn't thrown");
469        } catch (IllegalArgumentException iae) {
470            //expected
471        }
472    }
473
474    /**
475     * @tests javax.net.ssl.SSLSession#getValue(String name)
476     */
477    @TestTargetNew(
478        level = TestLevel.COMPLETE,
479        notes = "",
480        method = "getValue",
481        args = {String.class}
482    )
483    @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
484    public void test_getValue() {
485        SSLSession s = clientSession;
486        mySSLSessionBindingListener sbl = new mySSLSessionBindingListener();
487
488        try {
489            s.getValue(null);
490            fail("IllegalArgumentException wasn't thrown");
491        } catch (IllegalArgumentException iae) {
492            //expected
493        }
494
495        try {
496            s.putValue("Name", sbl);
497            Object obj = s.getValue("Name");
498            assertTrue(obj instanceof SSLSessionBindingListener);
499        } catch (Exception e) {
500            fail("Unexpected exception: " + e);
501        }
502    }
503
504    Thread serverThread, clientThread;
505    TestServer server;
506    TestClient client;
507
508    @Override
509    protected void setUp() {
510        port = Support_PortManager.getNextPort();
511        String serverKeys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS);
512        String clientKeys = (useBKS ? CLIENT_KEYS_BKS : CLIENT_KEYS_JKS);
513        server = new TestServer(true,
514                TestServer.CLIENT_AUTH_WANTED, serverKeys);
515        client = new TestClient(true, clientKeys);
516
517        serverThread = new Thread(server);
518        clientThread = new Thread(client);
519
520        serverThread.start();
521        try {
522            Thread.currentThread().sleep(1000);
523            clientThread.start();
524        } catch (InterruptedException e) {
525            fail("Could not create server or cient " + e.getMessage());
526        }
527        while (clientSession == null
528                && server.exception == null
529                && client.exception == null) {
530            try {
531                Thread.currentThread().sleep(500);
532            } catch (InterruptedException e) {
533                fail("couldn't create session");
534            }
535        }
536        assertNull("server thread has a pending exception: " + server.exception,
537                server.exception);
538        assertNull("client thread has a pending exception: " + client.exception,
539                client.exception);
540        assertNotNull("Could not initialize session", clientSession);
541    }
542
543    @Override
544    protected void tearDown() {
545        notFinished = false;
546        try {
547            serverThread.join();
548        } catch (InterruptedException e) {
549        }
550        try {
551            clientThread.join();
552        } catch (InterruptedException e) {
553        }
554
555        // The server must have completed without an exception.
556        if (server.getException() != null) {
557            throw new RuntimeException(server.getException());
558        }
559
560        // The client must have completed without an exception.
561        if (client.getException() != null) {
562            throw new RuntimeException(client.getException());
563        }
564    }
565
566    public class mySSLSessionBindingListener implements
567            SSLSessionBindingListener {
568        mySSLSessionBindingListener() {
569        }
570        public void valueBound(SSLSessionBindingEvent event) {}
571        public void valueUnbound(SSLSessionBindingEvent event) {}
572    }
573
574
575
576    String cipherSuiteBKS = "AES256-SHA";
577    /**
578     * Defines the keystore contents for the server, BKS version. Holds just a
579     * single self-generated key. The subject name is "Test Server".
580     */
581    private static final String SERVER_KEYS_BKS =
582        "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
583        "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
584        "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
585        "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
586        "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
587        "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
588        "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
589        "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
590        "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
591        "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
592        "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
593        "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
594        "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
595        "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
596        "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
597        "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
598        "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
599        "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
600        "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
601        "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
602        "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
603        "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
604        "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
605        "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
606
607    /**
608     * Defines the keystore contents for the client, BKS version. Holds just a
609     * single self-generated key. The subject name is "Test Client".
610     */
611    private static final String CLIENT_KEYS_BKS =
612        "AAAAAQAAABT4Rka6fxbFps98Y5k2VilmbibNkQAABfQEAAVteWtleQAAARpYl+POAAAAAQAFWC41" +
613        "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU9TANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
614        "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
615        "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgQ2xpZW50MB4XDTA4MDYwNTExNTg0NVoXDTA4MDkw" +
616        "MzExNTg0NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
617        "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVu" +
618        "dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUvmWsQDHPpbDKK13Yez2/q54tTOmRml/qva" +
619        "2K6dZjkjSTW0iRuk7ztaVEvdJpfVIDv1oBsCI51ttyLHROy1epjF+GoL74mJb7fkcd0VOoSOTjtD" +
620        "+3GgZkHPAm5YmUYxiJXqxKKJJqMCTIW46eJaA2nAep9QIwZ14/NFAs4ObV8CAwEAATANBgkqhkiG" +
621        "9w0BAQUFAAOBgQCJrCr3hZQFDlLIfsSKI1/w+BLvyf4fubOid0pBxfklR8KBNPTiqjSmu7pd/C/F" +
622        "1FR8CdZUDoPflZHCOU+fj5r5KUC1HyigY/tEUvlforBpfB0uCF+tXW4DbUfOWhfMtLV4nCOJOOZg" +
623        "awfZLJWBJouLKOp427vDftxTSB+Ks8YjlgAAAqwAAAAU+NH6TtrzjyDdCXm5B6Vo7xX5G4YAAAZx" +
624        "EAUkcZtmykn7YdaYxC1jRFJ+GEJpC8nZVg83QClVuCSIS8a5f8Hl44Bk4oepOZsPzhtz3RdVzDVi" +
625        "RFfoyZFsrk9F5bDTVJ6sQbb/1nfJkLhZFXokka0vND5AXMSoD5Bj1Fqem3cK7fSUyqKvFoRKC3XD" +
626        "FQvhqoam29F1rbl8FaYdPvhhZo8TfZQYUyUKwW+RbR44M5iHPx+ykieMe/C/4bcM3z8cwIbYI1aO" +
627        "gjQKS2MK9bs17xaDzeAh4sBKrskFGrDe+2dgvrSKdoakJhLTNTBSG6m+rzqMSCeQpafLKMSjTSSz" +
628        "+KoQ9bLyax8cbvViGGju0SlVhquloZmKOfHr8TukIoV64h3uCGFOVFtQjCYDOq6NbfRvMh14UVF5" +
629        "zgDIGczoD9dMoULWxBmniGSntoNgZM+QP6Id7DBasZGKfrHIAw3lHBqcvB5smemSu7F4itRoa3D8" +
630        "N7hhUEKAc+xA+8NKmXfiCBoHfPHTwDvt4IR7gWjeP3Xv5vitcKQ/MAfO5RwfzkYCXQ3FfjfzmsE1" +
631        "1IfLRDiBj+lhQSulhRVStKI88Che3M4JUNGKllrc0nt1pWa1vgzmUhhC4LSdm6trTHgyJnB6OcS9" +
632        "t2furYjK88j1AuB4921oxMxRm8c4Crq8Pyuf+n3YKi8Pl2BzBtw++0gj0ODlgwut8SrVj66/nvIB" +
633        "jN3kLVahR8nZrEFF6vTTmyXi761pzq9yOVqI57wJGx8o3Ygox1p+pWUPl1hQR7rrhUbgK/Q5wno9" +
634        "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef" +
635        "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
636
637    String cipherSuiteJKS = "SSL_RSA_WITH_RC4_128_MD5";
638    /**
639     * Defines the keystore contents for the server, JKS version. Holds just a
640     * single self-generated key. The subject name is "Test Server".
641     */
642    private static final String SERVER_KEYS_JKS =
643        "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC" +
644        "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4" +
645        "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du" +
646        "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo" +
647        "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk" +
648        "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc" +
649        "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3" +
650        "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk" +
651        "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH" +
652        "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs" +
653        "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq" +
654        "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg" +
655        "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu" +
656        "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD" +
657        "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH" +
658        "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0" +
659        "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w" +
660        "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf" +
661        "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg" +
662        "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT" +
663        "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB" +
664        "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW" +
665        "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY" +
666        "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
667
668    /**
669     * Defines the keystore contents for the client, JKS version. Holds just a
670     * single self-generated key. The subject name is "Test Client".
671     */
672    private static final String CLIENT_KEYS_JKS =
673        "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFhyMAAAArkwggK1MA4GCisGAQQBKgIRAQEFAASC" +
674        "AqGVSfXolBStZy4nnRNn4fAr+S7kfU2BS23wwW8uB2Ru3GvtLzlK9q08Gvq/LNqBafjyFTVL5FV5" +
675        "SED/8YomO5a98GpskSeRvytCiTBLJdgGhws5TOGekgIAcBROPGIyOtJPQ0HfOQs+BqgzGDHzHQhw" +
676        "u/8Tm6yQwiP+W/1I9B1QnaEztZA3mhTyMMJsmsFTYroGgAog885D5Cmzd8sYGfxec3R6I+xcmBAY" +
677        "eibR5kGpWwt1R+qMvRrtBqh5r6WSKhCBNax+SJVbtUNRiKyjKccdJg6fGqIWWeivwYTy0OhjA6b4" +
678        "NiZ/ZZs5pxFGWUj/Rlp0RYy8fCF6aw5/5s4Bf4MI6dPSqMG8Hf7sJR91GbcELyzPdM0h5lNavgit" +
679        "QPEzKeuDrGxhY1frJThBsNsS0gxeu+OgfJPEb/H4lpYX5IvuIGbWKcxoO9zq4/fimIZkdA8A+3eY" +
680        "mfDaowvy65NBVQPJSxaOyFhLHfeLqOeCsVENAea02vA7andZHTZehvcrqyKtm+z8ncHGRC2H9H8O" +
681        "jKwKHfxxrYY/jMAKLl00+PBb3kspO+BHI2EcQnQuMw/zr83OR9Meq4TJ0TMuNkApZELAeFckIBbS" +
682        "rBr8NNjAIfjuCTuKHhsTFWiHfk9ZIzigxXagfeDRiyVc6khOuF/bGorj23N2o7Rf3uLoU6PyXWi4" +
683        "uhctR1aL6NzxDoK2PbYCeA9hxbDv8emaVPIzlVwpPK3Ruvv9mkjcOhZ74J8bPK2fQmbplbOljcZi" +
684        "tZijOfzcO/11JrwhuJZRA6wanTqHoujgChV9EukVrmbWGGAcewFnAsSbFXIik7/+QznXaDIt5NgL" +
685        "H/Bcz4Z/fdV7Ae1eUaxKXdPbI//4J+8liVT/d8awjW2tldIaDlmGMR3aoc830+3mAAAAAQAFWC41" +
686        "MDkAAAJIMIICRDCCAa0CBEhHxLgwDQYJKoZIhvcNAQEEBQAwaTELMAkGA1UEBhMCVVMxEzARBgNV" +
687        "BAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01UVjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdB" +
688        "bmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVudDAeFw0wODA2MDUxMDQ5MjhaFw0wODA5MDMxMDQ5" +
689        "MjhaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzAN" +
690        "BgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBDbGllbnQwgZ8w" +
691        "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIK3Q+KiFbmCGg422TAo4gggdhMH6FJhiuz8DxRyeMKR" +
692        "UAfP4MK0wtc8N42waZ6OKvxpBFUy0BRfBsX0GD4Ku99yu9/tavSigTraeJtwV3WWRRjIqk7L3wX5" +
693        "cmgS2KSD43Y0rNUKrko26lnt9N4qiYRBSj+tcAN3Lx9+ptqk1LApAgMBAAEwDQYJKoZIhvcNAQEE" +
694        "BQADgYEANb7Q1GVSuy1RPJ0FmiXoMYCCtvlRLkmJphwxovK0cAQK12Vll+yAzBhHiQHy/RA11mng" +
695        "wYudC7u3P8X/tBT8GR1Yk7QW3KgFyPafp3lQBBCraSsfrjKj+dCLig1uBLUr4f68W8VFWZWWTHqp" +
696        "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw==";
697
698
699    int port;
700    SSLSocket serverSocket;
701    MyHandshakeListener listener;
702    String host = "localhost";
703    boolean notFinished = true;
704    SSLSession clientSession = null;
705    SSLContext clientSslContext = null;
706    String testData = "PING";
707
708    private String PASSWORD = "android";
709
710    String cipherSuite = (useBKS ? cipherSuiteBKS : cipherSuiteJKS);
711
712    /**
713     * Implements a test SSL socket server. It waits for a connection on a given
714     * port, requests client authentication (if specified), reads from the socket,
715     * and writes to the socket.
716     */
717    class TestServer implements Runnable {
718
719        public static final int CLIENT_AUTH_NONE = 0;
720
721        public static final int CLIENT_AUTH_WANTED = 1;
722
723        public static final int CLIENT_AUTH_NEEDED = 2;
724
725        private TestTrustManager trustManager;
726
727        private Exception exception;
728
729        String keys;
730
731        private int clientAuth;
732
733        private boolean provideKeys;
734
735        private KeyStore store;
736
737        public TestServer(boolean provideKeys, int clientAuth, String keys) {
738            this.keys = keys;
739            this.clientAuth = clientAuth;
740            this.provideKeys = provideKeys;
741
742            trustManager = new TestTrustManager();
743        }
744
745        public void run() {
746            try {
747                store = provideKeys ? getKeyStore(keys) : null;
748                KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null;
749                TrustManager[] trustManagers = new TrustManager[] { trustManager };
750
751                SSLContext sslContext = SSLContext.getInstance("TLS");
752                sslContext.init(keyManagers, trustManagers, null);
753
754                SSLServerSocket serverSocket = (SSLServerSocket)sslContext
755                        .getServerSocketFactory().createServerSocket();
756
757                if (clientAuth == CLIENT_AUTH_WANTED) {
758                    serverSocket.setWantClientAuth(true);
759                } else if (clientAuth == CLIENT_AUTH_NEEDED) {
760                    serverSocket.setNeedClientAuth(true);
761                } else {
762                    serverSocket.setWantClientAuth(false);
763                }
764
765                serverSocket.bind(new InetSocketAddress(port));
766
767                SSLSocket clientSocket = (SSLSocket)serverSocket.accept();
768
769                InputStream istream = clientSocket.getInputStream();
770                byte[] buffer = new byte[1024];
771                istream.read(buffer);
772
773                OutputStream ostream = clientSocket.getOutputStream();
774                ostream.write(testData.getBytes());
775                ostream.flush();
776
777                while (notFinished) {
778                    Thread.currentThread().sleep(500);
779                }
780
781                clientSocket.close();
782                serverSocket.close();
783
784            } catch (Exception ex) {
785                exception = ex;
786            }
787        }
788
789        public Exception getException() {
790            return exception;
791        }
792
793        public X509Certificate[] getChain() {
794            return trustManager.getChain();
795        }
796
797        public KeyStore getStore() {
798            return store;
799        }
800
801    }
802
803    /**
804     * Implements a test SSL socket client. It opens a connection to localhost on
805     * a given port, writes to the socket, and reads from the socket.
806     */
807    class TestClient implements Runnable {
808
809        private TestTrustManager trustManager;
810
811        private Exception exception;
812
813        private String keys;
814
815        private boolean provideKeys;
816
817        private KeyStore store;
818
819        public TestClient(boolean provideKeys, String keys) {
820            this.keys = keys;
821            this.provideKeys = provideKeys;
822
823            trustManager = new TestTrustManager();
824        }
825
826        public void run() {
827            try {
828                store = provideKeys ? getKeyStore(keys) : null;
829                KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null;
830                TrustManager[] trustManagers = new TrustManager[] { trustManager };
831
832                clientSslContext = SSLContext.getInstance("TLS");
833                clientSslContext.init(keyManagers, trustManagers, null);
834
835                SSLSocket socket = (SSLSocket)clientSslContext.getSocketFactory().createSocket();
836
837                socket.connect(new InetSocketAddress(port));
838                OutputStream ostream = socket.getOutputStream();
839                ostream.write(testData.getBytes());
840                ostream.flush();
841
842                InputStream istream = socket.getInputStream();
843                byte[] buffer = new byte[1024];
844                istream.read(buffer);
845
846                clientSession = socket.getSession();
847                while (notFinished) {
848                    Thread.currentThread().sleep(500);
849                }
850                socket.close();
851
852            } catch (Exception ex) {
853                exception = ex;
854            }
855        }
856
857        public Exception getException() {
858            return exception;
859        }
860
861        public X509Certificate[] getChain() {
862            return trustManager.getChain();
863        }
864
865        public KeyStore getStore() {
866            return store;
867        }
868    }
869
870    /**
871     * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
872     * for the result.
873     */
874    private KeyStore getKeyStore(String keys) throws Exception {
875        byte[] bytes = new Base64().decode(keys.getBytes());
876        InputStream inputStream = new ByteArrayInputStream(bytes);
877
878        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
879        keyStore.load(inputStream, PASSWORD.toCharArray());
880        inputStream.close();
881        return keyStore;
882    }
883
884    /**
885     * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
886     * for the result.
887     */
888    private KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception {
889        String algorithm = KeyManagerFactory.getDefaultAlgorithm();
890        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
891        keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
892
893        return keyManagerFactory.getKeyManagers();
894    }
895}
896