Home | History | Annotate | Download | only in ssl
      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 
     18 package tests.api.javax.net.ssl;
     19 
     20 import libcore.java.security.StandardNames;
     21 import java.io.ByteArrayInputStream;
     22 import java.io.InputStream;
     23 import java.io.OutputStream;
     24 import java.net.InetAddress;
     25 import java.net.InetSocketAddress;
     26 import java.security.KeyStore;
     27 import java.security.Principal;
     28 import java.security.cert.Certificate;
     29 import java.security.cert.X509Certificate;
     30 import javax.net.ssl.KeyManager;
     31 import javax.net.ssl.KeyManagerFactory;
     32 import javax.net.ssl.SSLContext;
     33 import javax.net.ssl.SSLServerSocket;
     34 import javax.net.ssl.SSLSession;
     35 import javax.net.ssl.SSLSessionBindingEvent;
     36 import javax.net.ssl.SSLSessionBindingListener;
     37 import javax.net.ssl.SSLSocket;
     38 import javax.net.ssl.TrustManager;
     39 import junit.framework.TestCase;
     40 import libcore.io.Base64;
     41 import tests.api.javax.net.ssl.HandshakeCompletedEventTest.MyHandshakeListener;
     42 import tests.api.javax.net.ssl.HandshakeCompletedEventTest.TestTrustManager;
     43 
     44 public class SSLSessionTest extends TestCase {
     45 
     46     // set to true if on Android, false if on RI
     47     boolean useBKS = true;
     48 
     49     /**
     50      * javax.net.ssl.SSLSession#getPeerHost()
     51      * javax.net.ssl.SSLSession#getPeerPort()
     52      */
     53     public void test_getPeerHost() throws Exception {
     54         SSLSession s = clientSession;
     55         assertEquals(InetAddress.getLocalHost().getHostName(), s.getPeerHost());
     56         assertEquals(serverSocket.getLocalPort(), s.getPeerPort());
     57     }
     58 
     59     /**
     60      * javax.net.ssl.SSLSession#invalidate()
     61      * javax.net.ssl.SSLSession#isValid()
     62      */
     63     public void test_invalidate() {
     64         SSLSession s = clientSession;
     65         assertTrue(s.isValid());
     66         s.invalidate();
     67         assertFalse(s.isValid());
     68     }
     69 
     70     /**
     71      * javax.net.ssl.SSLSession#getPeerPrincipal()
     72      */
     73     public void test_getPeerPrincipal() throws Exception {
     74         Principal p1 = clientSession.getPeerPrincipal();
     75         KeyStore store = server.getStore();
     76         X509Certificate cert = (X509Certificate)store.getCertificate("mykey");
     77         Principal p2 = cert.getSubjectX500Principal();
     78         assertEquals(p1, p2);
     79     }
     80 
     81     /**
     82      * javax.net.ssl.SSLSession#getApplicationBufferSize()
     83      */
     84     public void test_getApplicationBufferSize() {
     85         assertTrue(clientSession.getApplicationBufferSize() > 0);
     86     }
     87 
     88     /**
     89      * javax.net.ssl.SSLSession#getCipherSuite()
     90      */
     91     public void test_getCipherSuite() {
     92         // Identify the expected cipher suite from the expected list of cipher suites enabled by
     93         // default.
     94         // This test class initializes the server with an RSA key. Thus, only cipher suites that
     95         // authenticate the server using RSA are expected to be used.
     96         String expectedCipherSuite = null;
     97         for (String cipherSuite : StandardNames.CIPHER_SUITES_DEFAULT) {
     98             if (cipherSuite.contains("_RSA_")) {
     99                 expectedCipherSuite = cipherSuite;
    100                 break;
    101             }
    102         }
    103         if (expectedCipherSuite == null) {
    104             fail("Failed to identify expected cipher suite");
    105         }
    106         assertEquals(expectedCipherSuite, clientSession.getCipherSuite());
    107     }
    108 
    109     /**
    110      * javax.net.ssl.SSLSession#getCreationTime()
    111      */
    112     public void test_getCreationTime() {
    113         // check if creation time was in the last 10 seconds
    114         long currentTime = System.currentTimeMillis();
    115         long sessionTime = clientSession.getCreationTime();
    116         long diff = currentTime - sessionTime;
    117         assertTrue("diff between " + currentTime + " and " + sessionTime + " should be < 10000",
    118                    diff < 10000);
    119     }
    120 
    121     /**
    122      * javax.net.ssl.SSLSession#getId()
    123      */
    124     public void test_getId() {
    125         byte[] id = clientSession.getId();
    126         SSLSession sess = clientSslContext.getClientSessionContext().getSession(id);
    127         assertNotNull("Could not find session for id " + id, sess);
    128         assertEquals(clientSession, sess);
    129     }
    130 
    131     /**
    132      * javax.net.ssl.SSLSession#getLastAccessedTime()
    133      */
    134     public void test_getLastAccessedTime() {
    135         // check if last access time was in the last 10 seconds
    136         long currentTime = System.currentTimeMillis();
    137         long sessionTime = clientSession.getLastAccessedTime();
    138         long diff = currentTime - sessionTime;
    139         assertTrue("diff between " + currentTime + " and " + sessionTime + " should be < 10000",
    140                    diff < 10000);
    141         assertTrue ("diff should be < 10000 but is " + diff, diff < 10000);
    142     }
    143 
    144     /**
    145      * javax.net.ssl.SSLSession#getLocalCertificates()
    146      */
    147     public void test_getLocalCertificates() throws Exception {
    148         KeyStore store = client.getStore();
    149         Certificate cert = store.getCertificate("mykey");
    150         Certificate[] certs = clientSession.getLocalCertificates();
    151         assertEquals(cert, certs[0]);
    152     }
    153 
    154     /**
    155      * javax.net.ssl.SSLSession#getLocalPrincipal()
    156      */
    157     public void test_getLocalPrincipal() throws Exception {
    158         Principal p1 = clientSession.getLocalPrincipal();
    159         KeyStore store = client.getStore();
    160         X509Certificate cert = (X509Certificate)store.getCertificate("mykey");
    161         Principal p2 = cert.getSubjectX500Principal();
    162         assertEquals(p1, p2);
    163     }
    164 
    165     /**
    166      * javax.net.ssl.SSLSession#getPacketBufferSize()
    167      */
    168     public void test_getPacketBufferSize() {
    169         assertTrue(clientSession.getPacketBufferSize() > 0);
    170     }
    171 
    172     /**
    173      * javax.net.ssl.SSLSession#getPeerCertificates()
    174      */
    175     public void test_getPeerCertificates() throws Exception {
    176         Certificate[] res = clientSession.getPeerCertificates();
    177         assertTrue(res.length > 0);
    178     }
    179 
    180     /**
    181      * javax.net.ssl.SSLSession#getPeerCertificateChain()
    182      */
    183     public void test_getPeerCertificateChain() throws Exception {
    184         javax.security.cert.X509Certificate[] res = clientSession.getPeerCertificateChain();
    185         assertTrue(res.length > 0);
    186     }
    187 
    188     /**
    189      * javax.net.ssl.SSLSession#getProtocol()
    190      */
    191     public void test_getProtocol() {
    192         assertEquals("TLSv1.2", clientSession.getProtocol());
    193     }
    194 
    195     /**
    196      * javax.net.ssl.SSLSession#getSessionContext()
    197      */
    198     public void test_getSessionContext() {
    199         assertEquals(clientSession.getSessionContext(),
    200                      clientSslContext.getClientSessionContext());
    201     }
    202 
    203     /**
    204      * javax.net.ssl.SSLSession#putValue(String name, Object value)
    205      * javax.net.ssl.SSLSession#removeValue(String name)
    206      * javax.net.ssl.SSLSession#getValueNames()
    207      */
    208     public void test_putValue() {
    209         SSLSession s = clientSession;
    210         mySSLSessionBindingListener sbl = new mySSLSessionBindingListener();
    211         assertNotNull(s.getValueNames());
    212         assertEquals(0, s.getValueNames().length);
    213         s.putValue("Name_01", sbl);
    214         s.putValue("Name_02", sbl);
    215         s.putValue("Name_03", sbl);
    216         assertEquals(3, s.getValueNames().length);
    217         s.removeValue("Name_01");
    218         assertEquals(2, s.getValueNames().length);
    219 
    220         try {
    221             s.putValue(null, null);
    222             fail("IllegalArgumentException wasn't thrown");
    223         } catch (IllegalArgumentException expected) {
    224             // expected
    225         }
    226         try {
    227             s.putValue("ABC", null);
    228             fail("IllegalArgumentException wasn't thrown");
    229         } catch (IllegalArgumentException expected) {
    230             // expected
    231         }
    232         try {
    233             s.putValue(null, sbl);
    234             fail("IllegalArgumentException wasn't thrown");
    235         } catch (IllegalArgumentException expected) {
    236             // expected
    237         }
    238 
    239         try {
    240             s.removeValue(null);
    241             fail("IllegalArgumentException wasn't thrown");
    242         } catch (IllegalArgumentException expected) {
    243             // expected
    244         }
    245     }
    246 
    247     /**
    248      * javax.net.ssl.SSLSession#getValue(String name)
    249      */
    250     public void test_getValue() {
    251         SSLSession s = clientSession;
    252         mySSLSessionBindingListener sbl = new mySSLSessionBindingListener();
    253 
    254         try {
    255             s.getValue(null);
    256             fail("IllegalArgumentException wasn't thrown");
    257         } catch (IllegalArgumentException expected) {
    258             // expected
    259         }
    260 
    261         s.putValue("Name", sbl);
    262         Object obj = s.getValue("Name");
    263         assertTrue(obj instanceof SSLSessionBindingListener);
    264     }
    265 
    266     Thread serverThread, clientThread;
    267     TestServer server;
    268     TestClient client;
    269 
    270     @Override
    271     protected void setUp() throws Exception {
    272         String serverKeys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS);
    273         String clientKeys = (useBKS ? CLIENT_KEYS_BKS : CLIENT_KEYS_JKS);
    274         server = new TestServer(true, TestServer.CLIENT_AUTH_WANTED, serverKeys);
    275         client = new TestClient(true, clientKeys);
    276 
    277         serverThread = new Thread(server);
    278         clientThread = new Thread(client);
    279 
    280         serverThread.start();
    281         try {
    282             Thread.currentThread().sleep(1000);
    283             clientThread.start();
    284         } catch (InterruptedException e) {
    285             fail("Could not create server or cient " + e.getMessage());
    286         }
    287         while (clientSession == null
    288                 && server.exception == null
    289                 && client.exception == null) {
    290             try {
    291                 Thread.currentThread().sleep(500);
    292             } catch (InterruptedException e) {
    293                 fail("couldn't create session");
    294             }
    295         }
    296         if (server.exception != null) {
    297             server.exception.printStackTrace();
    298         }
    299         assertNull("server thread has a pending exception: " + server.exception,
    300                 server.exception);
    301         if (client.exception != null) {
    302             client.exception.printStackTrace();
    303         }
    304         assertNull("client thread has a pending exception: " + client.exception,
    305                 client.exception);
    306         assertNotNull("Could not initialize session", clientSession);
    307     }
    308 
    309     @Override
    310     protected void tearDown() {
    311         notFinished = false;
    312         try {
    313             serverThread.join();
    314         } catch (InterruptedException e) {
    315             throw new RuntimeException(e);
    316         }
    317         try {
    318             clientThread.join();
    319         } catch (InterruptedException e) {
    320             throw new RuntimeException(e);
    321         }
    322 
    323         // The server must have completed without an exception.
    324         if (server.getException() != null) {
    325             throw new RuntimeException(server.getException());
    326         }
    327 
    328         // The client must have completed without an exception.
    329         if (client.getException() != null) {
    330             throw new RuntimeException(client.getException());
    331         }
    332     }
    333 
    334     public class mySSLSessionBindingListener implements
    335             SSLSessionBindingListener {
    336         mySSLSessionBindingListener() {
    337         }
    338         public void valueBound(SSLSessionBindingEvent event) {}
    339         public void valueUnbound(SSLSessionBindingEvent event) {}
    340     }
    341 
    342     /**
    343      * Defines the keystore contents for the server, BKS version. Holds just a
    344      * single self-generated key. The subject name is "Test Server".
    345      */
    346     private static final String SERVER_KEYS_BKS =
    347             "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41"
    348             + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
    349             + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
    350             + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw"
    351             + "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
    352             + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl"
    353             + "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy"
    354             + "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV"
    355             + "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG"
    356             + "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU"
    357             + "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV"
    358             + "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx"
    359             + "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR"
    360             + "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN"
    361             + "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs"
    362             + "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck"
    363             + "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM"
    364             + "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI"
    365             + "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f"
    366             + "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx"
    367             + "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt"
    368             + "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw"
    369             + "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl"
    370             + "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
    371 
    372     /**
    373      * Defines the keystore contents for the client, BKS version. Holds just a
    374      * single self-generated key. The subject name is "Test Client".
    375      */
    376     private static final String CLIENT_KEYS_BKS =
    377             "AAAAAQAAABT4Rka6fxbFps98Y5k2VilmbibNkQAABfQEAAVteWtleQAAARpYl+POAAAAAQAFWC41"
    378             + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU9TANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
    379             + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
    380             + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgQ2xpZW50MB4XDTA4MDYwNTExNTg0NVoXDTA4MDkw"
    381             + "MzExNTg0NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
    382             + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVu"
    383             + "dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUvmWsQDHPpbDKK13Yez2/q54tTOmRml/qva"
    384             + "2K6dZjkjSTW0iRuk7ztaVEvdJpfVIDv1oBsCI51ttyLHROy1epjF+GoL74mJb7fkcd0VOoSOTjtD"
    385             + "+3GgZkHPAm5YmUYxiJXqxKKJJqMCTIW46eJaA2nAep9QIwZ14/NFAs4ObV8CAwEAATANBgkqhkiG"
    386             + "9w0BAQUFAAOBgQCJrCr3hZQFDlLIfsSKI1/w+BLvyf4fubOid0pBxfklR8KBNPTiqjSmu7pd/C/F"
    387             + "1FR8CdZUDoPflZHCOU+fj5r5KUC1HyigY/tEUvlforBpfB0uCF+tXW4DbUfOWhfMtLV4nCOJOOZg"
    388             + "awfZLJWBJouLKOp427vDftxTSB+Ks8YjlgAAAqwAAAAU+NH6TtrzjyDdCXm5B6Vo7xX5G4YAAAZx"
    389             + "EAUkcZtmykn7YdaYxC1jRFJ+GEJpC8nZVg83QClVuCSIS8a5f8Hl44Bk4oepOZsPzhtz3RdVzDVi"
    390             + "RFfoyZFsrk9F5bDTVJ6sQbb/1nfJkLhZFXokka0vND5AXMSoD5Bj1Fqem3cK7fSUyqKvFoRKC3XD"
    391             + "FQvhqoam29F1rbl8FaYdPvhhZo8TfZQYUyUKwW+RbR44M5iHPx+ykieMe/C/4bcM3z8cwIbYI1aO"
    392             + "gjQKS2MK9bs17xaDzeAh4sBKrskFGrDe+2dgvrSKdoakJhLTNTBSG6m+rzqMSCeQpafLKMSjTSSz"
    393             + "+KoQ9bLyax8cbvViGGju0SlVhquloZmKOfHr8TukIoV64h3uCGFOVFtQjCYDOq6NbfRvMh14UVF5"
    394             + "zgDIGczoD9dMoULWxBmniGSntoNgZM+QP6Id7DBasZGKfrHIAw3lHBqcvB5smemSu7F4itRoa3D8"
    395             + "N7hhUEKAc+xA+8NKmXfiCBoHfPHTwDvt4IR7gWjeP3Xv5vitcKQ/MAfO5RwfzkYCXQ3FfjfzmsE1"
    396             + "1IfLRDiBj+lhQSulhRVStKI88Che3M4JUNGKllrc0nt1pWa1vgzmUhhC4LSdm6trTHgyJnB6OcS9"
    397             + "t2furYjK88j1AuB4921oxMxRm8c4Crq8Pyuf+n3YKi8Pl2BzBtw++0gj0ODlgwut8SrVj66/nvIB"
    398             + "jN3kLVahR8nZrEFF6vTTmyXi761pzq9yOVqI57wJGx8o3Ygox1p+pWUPl1hQR7rrhUbgK/Q5wno9"
    399             + "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef"
    400             + "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
    401 
    402     /**
    403      * Defines the keystore contents for the server, JKS version. Holds just a
    404      * single self-generated key. The subject name is "Test Server".
    405      */
    406     private static final String SERVER_KEYS_JKS =
    407             "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC"
    408             + "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4"
    409             + "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du"
    410             + "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo"
    411             + "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk"
    412             + "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc"
    413             + "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3"
    414             + "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk"
    415             + "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH"
    416             + "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs"
    417             + "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq"
    418             + "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg"
    419             + "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu"
    420             + "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD"
    421             + "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH"
    422             + "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0"
    423             + "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w"
    424             + "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf"
    425             + "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg"
    426             + "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT"
    427             + "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB"
    428             + "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW"
    429             + "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY"
    430             + "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
    431 
    432     /**
    433      * Defines the keystore contents for the client, JKS version. Holds just a
    434      * single self-generated key. The subject name is "Test Client".
    435      */
    436     private static final String CLIENT_KEYS_JKS =
    437             "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFhyMAAAArkwggK1MA4GCisGAQQBKgIRAQEFAASC"
    438             + "AqGVSfXolBStZy4nnRNn4fAr+S7kfU2BS23wwW8uB2Ru3GvtLzlK9q08Gvq/LNqBafjyFTVL5FV5"
    439             + "SED/8YomO5a98GpskSeRvytCiTBLJdgGhws5TOGekgIAcBROPGIyOtJPQ0HfOQs+BqgzGDHzHQhw"
    440             + "u/8Tm6yQwiP+W/1I9B1QnaEztZA3mhTyMMJsmsFTYroGgAog885D5Cmzd8sYGfxec3R6I+xcmBAY"
    441             + "eibR5kGpWwt1R+qMvRrtBqh5r6WSKhCBNax+SJVbtUNRiKyjKccdJg6fGqIWWeivwYTy0OhjA6b4"
    442             + "NiZ/ZZs5pxFGWUj/Rlp0RYy8fCF6aw5/5s4Bf4MI6dPSqMG8Hf7sJR91GbcELyzPdM0h5lNavgit"
    443             + "QPEzKeuDrGxhY1frJThBsNsS0gxeu+OgfJPEb/H4lpYX5IvuIGbWKcxoO9zq4/fimIZkdA8A+3eY"
    444             + "mfDaowvy65NBVQPJSxaOyFhLHfeLqOeCsVENAea02vA7andZHTZehvcrqyKtm+z8ncHGRC2H9H8O"
    445             + "jKwKHfxxrYY/jMAKLl00+PBb3kspO+BHI2EcQnQuMw/zr83OR9Meq4TJ0TMuNkApZELAeFckIBbS"
    446             + "rBr8NNjAIfjuCTuKHhsTFWiHfk9ZIzigxXagfeDRiyVc6khOuF/bGorj23N2o7Rf3uLoU6PyXWi4"
    447             + "uhctR1aL6NzxDoK2PbYCeA9hxbDv8emaVPIzlVwpPK3Ruvv9mkjcOhZ74J8bPK2fQmbplbOljcZi"
    448             + "tZijOfzcO/11JrwhuJZRA6wanTqHoujgChV9EukVrmbWGGAcewFnAsSbFXIik7/+QznXaDIt5NgL"
    449             + "H/Bcz4Z/fdV7Ae1eUaxKXdPbI//4J+8liVT/d8awjW2tldIaDlmGMR3aoc830+3mAAAAAQAFWC41"
    450             + "MDkAAAJIMIICRDCCAa0CBEhHxLgwDQYJKoZIhvcNAQEEBQAwaTELMAkGA1UEBhMCVVMxEzARBgNV"
    451             + "BAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01UVjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdB"
    452             + "bmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVudDAeFw0wODA2MDUxMDQ5MjhaFw0wODA5MDMxMDQ5"
    453             + "MjhaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzAN"
    454             + "BgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBDbGllbnQwgZ8w"
    455             + "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIK3Q+KiFbmCGg422TAo4gggdhMH6FJhiuz8DxRyeMKR"
    456             + "UAfP4MK0wtc8N42waZ6OKvxpBFUy0BRfBsX0GD4Ku99yu9/tavSigTraeJtwV3WWRRjIqk7L3wX5"
    457             + "cmgS2KSD43Y0rNUKrko26lnt9N4qiYRBSj+tcAN3Lx9+ptqk1LApAgMBAAEwDQYJKoZIhvcNAQEE"
    458             + "BQADgYEANb7Q1GVSuy1RPJ0FmiXoMYCCtvlRLkmJphwxovK0cAQK12Vll+yAzBhHiQHy/RA11mng"
    459             + "wYudC7u3P8X/tBT8GR1Yk7QW3KgFyPafp3lQBBCraSsfrjKj+dCLig1uBLUr4f68W8VFWZWWTHqp"
    460             + "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw==";
    461 
    462 
    463     SSLServerSocket serverSocket;
    464     MyHandshakeListener listener;
    465     String host = "localhost";
    466     boolean notFinished = true;
    467     SSLSession clientSession = null;
    468     SSLContext clientSslContext = null;
    469     String testData = "PING";
    470 
    471     private String PASSWORD = "android";
    472 
    473     /**
    474      * Implements a test SSL socket server. It waits for a connection on a given
    475      * port, requests client authentication (if specified), reads from the socket,
    476      * and writes to the socket.
    477      */
    478     class TestServer implements Runnable {
    479 
    480         public static final int CLIENT_AUTH_NONE = 0;
    481 
    482         public static final int CLIENT_AUTH_WANTED = 1;
    483 
    484         public static final int CLIENT_AUTH_NEEDED = 2;
    485 
    486         private TestTrustManager trustManager;
    487 
    488         private Exception exception;
    489 
    490         String keys;
    491 
    492         private int clientAuth;
    493 
    494         private boolean provideKeys;
    495 
    496         private KeyStore store;
    497 
    498         public TestServer(boolean provideKeys, int clientAuth, String keys) throws Exception {
    499             this.keys = keys;
    500             this.clientAuth = clientAuth;
    501             this.provideKeys = provideKeys;
    502 
    503             trustManager = new TestTrustManager();
    504 
    505             store = provideKeys ? getKeyStore(keys) : null;
    506             KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null;
    507             TrustManager[] trustManagers = new TrustManager[] { trustManager };
    508 
    509             SSLContext sslContext = SSLContext.getInstance("TLS");
    510             sslContext.init(keyManagers, trustManagers, null);
    511 
    512             serverSocket = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket();
    513 
    514             if (clientAuth == CLIENT_AUTH_WANTED) {
    515                 serverSocket.setWantClientAuth(true);
    516             } else if (clientAuth == CLIENT_AUTH_NEEDED) {
    517                 serverSocket.setNeedClientAuth(true);
    518             } else {
    519                 serverSocket.setWantClientAuth(false);
    520             }
    521 
    522             serverSocket.bind(null);
    523         }
    524 
    525         public void run() {
    526             try {
    527                 SSLSocket clientSocket = (SSLSocket)serverSocket.accept();
    528 
    529                 InputStream istream = clientSocket.getInputStream();
    530                 byte[] buffer = new byte[1024];
    531                 istream.read(buffer);
    532 
    533                 OutputStream ostream = clientSocket.getOutputStream();
    534                 ostream.write(testData.getBytes());
    535                 ostream.flush();
    536 
    537                 while (notFinished) {
    538                     Thread.currentThread().sleep(500);
    539                 }
    540 
    541                 clientSocket.close();
    542                 serverSocket.close();
    543 
    544             } catch (Exception ex) {
    545                 exception = ex;
    546             }
    547         }
    548 
    549         public Exception getException() {
    550             return exception;
    551         }
    552 
    553         public javax.security.cert.X509Certificate[] getChain() {
    554             return trustManager.getChain();
    555         }
    556 
    557         public KeyStore getStore() {
    558             return store;
    559         }
    560 
    561     }
    562 
    563     /**
    564      * Implements a test SSL socket client. It opens a connection to localhost on
    565      * a given port, writes to the socket, and reads from the socket.
    566      */
    567     class TestClient implements Runnable {
    568 
    569         private TestTrustManager trustManager;
    570 
    571         private Exception exception;
    572 
    573         private String keys;
    574 
    575         private boolean provideKeys;
    576 
    577         private KeyStore store;
    578 
    579         public TestClient(boolean provideKeys, String keys) {
    580             this.keys = keys;
    581             this.provideKeys = provideKeys;
    582 
    583             trustManager = new TestTrustManager();
    584         }
    585 
    586         public void run() {
    587             try {
    588                 store = provideKeys ? getKeyStore(keys) : null;
    589                 KeyManager[] keyManagers = store != null ? getKeyManagers(store) : null;
    590                 TrustManager[] trustManagers = new TrustManager[] { trustManager };
    591 
    592                 clientSslContext = SSLContext.getInstance("TLS");
    593                 clientSslContext.init(keyManagers, trustManagers, null);
    594 
    595                 SSLSocket socket = (SSLSocket)clientSslContext.getSocketFactory().createSocket();
    596 
    597                 socket.connect(serverSocket.getLocalSocketAddress());
    598                 OutputStream ostream = socket.getOutputStream();
    599                 ostream.write(testData.getBytes());
    600                 ostream.flush();
    601 
    602                 InputStream istream = socket.getInputStream();
    603                 byte[] buffer = new byte[1024];
    604                 istream.read(buffer);
    605 
    606                 clientSession = socket.getSession();
    607                 while (notFinished) {
    608                     Thread.currentThread().sleep(500);
    609                 }
    610                 socket.close();
    611 
    612             } catch (Exception ex) {
    613                 exception = ex;
    614             }
    615         }
    616 
    617         public Exception getException() {
    618             return exception;
    619         }
    620 
    621         public javax.security.cert.X509Certificate[] getChain() {
    622             return trustManager.getChain();
    623         }
    624 
    625         public KeyStore getStore() {
    626             return store;
    627         }
    628     }
    629 
    630     /**
    631      * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
    632      * for the result.
    633      */
    634     private KeyStore getKeyStore(String keys) throws Exception {
    635         byte[] bytes = Base64.decode(keys.getBytes());
    636         InputStream inputStream = new ByteArrayInputStream(bytes);
    637 
    638         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    639         keyStore.load(inputStream, PASSWORD.toCharArray());
    640         inputStream.close();
    641         return keyStore;
    642     }
    643 
    644     /**
    645      * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
    646      * for the result.
    647      */
    648     private KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception {
    649         String algorithm = KeyManagerFactory.getDefaultAlgorithm();
    650         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    651         keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
    652 
    653         return keyManagerFactory.getKeyManagers();
    654     }
    655 }
    656