1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package tests.api.javax.net.ssl; 18 19 import junit.framework.TestCase; 20 21 import libcore.io.Base64; 22 23 import java.io.ByteArrayInputStream; 24 import java.io.IOException; 25 import java.io.InputStream; 26 import java.net.InetAddress; 27 import java.security.KeyStore; 28 import java.security.SecureRandom; 29 import java.util.Arrays; 30 31 import javax.net.ssl.KeyManager; 32 import javax.net.ssl.KeyManagerFactory; 33 import javax.net.ssl.SSLContext; 34 import javax.net.ssl.SSLServerSocket; 35 36 public class SSLServerSocketTest extends TestCase { 37 38 // set to true if on Android, false if on RI 39 boolean useBKS = true; 40 41 /** 42 * Additional class for SSLServerSocket constructor verification 43 */ 44 class mySSLServerSocket extends SSLServerSocket { 45 46 public mySSLServerSocket() throws IOException{ 47 super(); 48 } 49 50 public mySSLServerSocket(int port) throws IOException{ 51 super(port); 52 } 53 54 public mySSLServerSocket(int port, int backlog) throws IOException{ 55 super(port, backlog); 56 } 57 58 public mySSLServerSocket(int port, int backlog, InetAddress address) throws IOException{ 59 super(port, backlog, address); 60 } 61 62 public String[] getSupportedCipherSuites() { 63 return null; 64 } 65 66 public void setEnabledCipherSuites(String[] suites) { 67 68 } 69 70 public String[] getEnabledCipherSuites() { 71 return null; 72 } 73 74 public String[] getSupportedProtocols() { 75 return null; 76 } 77 78 public String[] getEnabledProtocols() { 79 return null; 80 } 81 82 public void setEnabledProtocols(String[] protocols) { 83 84 } 85 86 public void setEnableSessionCreation(boolean flag) { 87 88 } 89 90 public boolean getEnableSessionCreation() { 91 return false; 92 } 93 94 public void setNeedClientAuth(boolean need) { 95 96 } 97 98 public boolean getNeedClientAuth() { 99 return false; 100 } 101 102 public boolean getUseClientMode() { 103 return false; 104 } 105 106 public void setUseClientMode(boolean mode) { 107 108 } 109 110 public boolean getWantClientAuth() { 111 return false; 112 } 113 public void setWantClientAuth(boolean mode) { 114 115 } 116 } 117 118 /** 119 * javax.net.ssl.SSLServerSocket#SSLServerSocket() 120 */ 121 public void testConstructor() throws Exception { 122 SSLServerSocket ssl = new mySSLServerSocket(); 123 } 124 125 /** 126 * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port) 127 */ 128 public void testConstructor_I() throws Exception { 129 int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE}; 130 131 SSLServerSocket ssl = new mySSLServerSocket(0); 132 133 for (int i = 0; i < port_invalid.length; i++) { 134 try { 135 new mySSLServerSocket(port_invalid[i]); 136 fail("IllegalArgumentException should be thrown"); 137 } catch (IllegalArgumentException expected) { 138 } 139 } 140 141 try { 142 new mySSLServerSocket(ssl.getLocalPort()); 143 fail("IOException Expected when opening an already opened port"); 144 } catch (IOException expected) { 145 } 146 } 147 148 /** 149 * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog) 150 */ 151 public void testConstructor_II() throws Exception { 152 mySSLServerSocket ssl = new mySSLServerSocket(0, 1); 153 int[] port_invalid = {-1, Integer.MIN_VALUE, Integer.MAX_VALUE}; 154 155 for (int i = 0; i < port_invalid.length; i++) { 156 try { 157 new mySSLServerSocket(port_invalid[i], 1); 158 fail("IllegalArgumentException should be thrown"); 159 } catch (IllegalArgumentException expected) { 160 } 161 } 162 163 try { 164 new mySSLServerSocket(ssl.getLocalPort(), 1); 165 fail("IOException should be thrown"); 166 } catch (IOException expected) { 167 } 168 } 169 170 /** 171 * javax.net.ssl.SSLServerSocket#SSLServerSocket(int port, int backlog, InetAddress address) 172 */ 173 public void testConstructor_IIInetAddress() throws Exception { 174 // A null InetAddress is okay. 175 new mySSLServerSocket(0, 0, null); 176 177 int[] port_invalid = {-1, 65536, Integer.MIN_VALUE, Integer.MAX_VALUE}; 178 179 mySSLServerSocket ssl = new mySSLServerSocket(0, 0, InetAddress.getLocalHost()); 180 181 for (int i = 0; i < port_invalid.length; i++) { 182 try { 183 new mySSLServerSocket(port_invalid[i], 1, InetAddress.getLocalHost()); 184 fail("IllegalArgumentException should be thrown"); 185 } catch (IllegalArgumentException expected) { 186 } 187 } 188 189 try { 190 new mySSLServerSocket(ssl.getLocalPort(), 0, InetAddress.getLocalHost()); 191 fail("IOException should be thrown for"); 192 } catch (IOException expected) { 193 } 194 } 195 196 /** 197 * @throws Exception 198 * javax.net.ssl.SSLServerSocket#getSupportedCipherSuites() 199 */ 200 public void test_getSupportedCipherSuites() throws Exception { 201 SSLServerSocket sss = getSSLServerSocket(); 202 String[] res = sss.getSupportedCipherSuites(); 203 assertNotNull("NULL result", res); 204 assertTrue("no supported cipher suites available.", res.length > 0); 205 } 206 207 /** 208 * @throws IOException 209 * javax.net.ssl.SSLServerSocket#getEnabledCipherSuites() 210 * javax.net.ssl.SSLServerSocket#setEnabledCipherSuites(String[] suites) 211 */ 212 public void test_EnabledCipherSuites() throws Exception { 213 SSLServerSocket sss = getSSLServerSocket(); 214 try { 215 sss.setEnabledCipherSuites(null); 216 } catch (IllegalArgumentException iae) { 217 //expected 218 } 219 String[] unsupportedCipherSuites = {"unsupported"}; 220 try { 221 sss.setEnabledCipherSuites(unsupportedCipherSuites); 222 } catch (IllegalArgumentException iae) { 223 //expected 224 } 225 int count = sss.getSupportedCipherSuites().length; 226 assertTrue("No supported cipher suites", count > 0); 227 sss.setEnabledCipherSuites(sss.getSupportedCipherSuites()); 228 String[] res = sss.getEnabledCipherSuites(); 229 assertNotNull("NULL result", res); 230 assertEquals("not all supported cipher suites were enabled", 231 Arrays.asList(sss.getSupportedCipherSuites()), 232 Arrays.asList(res)); 233 } 234 235 /** 236 * @throws IOException 237 * javax.net.ssl.SSLServerSocket#getSupportedProtocols() 238 */ 239 public void test_getSupportedProtocols() throws Exception { 240 SSLServerSocket sss = getSSLServerSocket(); 241 String[] res = sss.getSupportedCipherSuites(); 242 assertNotNull("NULL result", res); 243 assertTrue("no supported protocols available.", res.length > 0); 244 } 245 246 /** 247 * @throws IOException 248 * javax.net.ssl.SSLServerSocket#getEnabledProtocols() 249 * javax.net.ssl.SSLServerSocket#setEnabledProtocols(String[] protocols) 250 */ 251 public void test_EnabledProtocols() throws Exception { 252 SSLServerSocket sss = getSSLServerSocket(); 253 try { 254 sss.setEnabledProtocols(null); 255 } catch (IllegalArgumentException iae) { 256 //expected 257 } 258 String[] unsupportedProtocols = {"unsupported"}; 259 try { 260 sss.setEnabledProtocols(unsupportedProtocols); 261 } catch (IllegalArgumentException iae) { 262 //expected 263 } 264 int count = sss.getSupportedProtocols().length; 265 assertTrue("No supported protocols", count > 0); 266 sss.setEnabledProtocols(sss.getSupportedProtocols()); 267 String[] res = sss.getEnabledProtocols(); 268 assertNotNull("NULL result", res); 269 assertTrue("no enabled protocols.", res.length == count); 270 } 271 272 /** 273 * @throws IOException 274 * javax.net.ssl.SSLServerSocket#setEnableSessionCreation(boolean flag) 275 * javax.net.ssl.SSLServerSocket#getEnableSessionCreation() 276 */ 277 public void test_EnableSessionCreation() throws Exception { 278 SSLServerSocket sss = getSSLServerSocket(); 279 assertTrue(sss.getEnableSessionCreation()); 280 sss.setEnableSessionCreation(false); 281 assertFalse(sss.getEnableSessionCreation()); 282 sss.setEnableSessionCreation(true); 283 assertTrue(sss.getEnableSessionCreation()); 284 } 285 286 /** 287 * @throws IOException 288 * javax.net.ssl.SSLServerSocket#setNeedClientAuth(boolean need) 289 * javax.net.ssl.SSLServerSocket#getNeedClientAuthCreation() 290 */ 291 public void test_NeedClientAuth() throws Exception { 292 SSLServerSocket sss = getSSLServerSocket(); 293 sss.setNeedClientAuth(true); 294 assertTrue(sss.getNeedClientAuth()); 295 sss.setNeedClientAuth(false); 296 assertFalse(sss.getNeedClientAuth()); 297 } 298 299 /** 300 * @throws IOException 301 * javax.net.ssl.SSLServerSocket#getUseClientMode() 302 * javax.net.ssl.SSLServerSocket#setUseClientMode(boolean mode) 303 */ 304 public void test_UseClientMode() throws Exception { 305 SSLServerSocket sss = getSSLServerSocket(); 306 sss.setUseClientMode(false); 307 assertFalse(sss.getUseClientMode()); 308 sss.setUseClientMode(true); 309 assertTrue(sss.getUseClientMode()); 310 } 311 312 /** 313 * @throws IOException 314 * javax.net.ssl.SSLServerSocket#setWantClientAuth(boolean want) 315 * javax.net.ssl.SSLServerSocket#getWantClientAuthCreation() 316 */ 317 public void test_WantClientAuth() throws Exception { 318 SSLServerSocket sss = getSSLServerSocket(); 319 sss.setWantClientAuth(true); 320 assertTrue(sss.getWantClientAuth()); 321 sss.setWantClientAuth(false); 322 assertFalse(sss.getWantClientAuth()); 323 } 324 325 326 /** 327 * Defines the keystore contents for the server, BKS version. Holds just a 328 * single self-generated key. The subject name is "Test Server". 329 */ 330 private static final String SERVER_KEYS_BKS = 331 "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" + 332 "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" + 333 "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" + 334 "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" + 335 "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" + 336 "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" + 337 "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" + 338 "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" + 339 "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" + 340 "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" + 341 "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" + 342 "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" + 343 "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" + 344 "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" + 345 "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" + 346 "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" + 347 "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" + 348 "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" + 349 "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" + 350 "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" + 351 "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" + 352 "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" + 353 "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" + 354 "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw="; 355 356 /** 357 * Defines the keystore contents for the server, JKS version. Holds just a 358 * single self-generated key. The subject name is "Test Server". 359 */ 360 private static final String SERVER_KEYS_JKS = 361 "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC" + 362 "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4" + 363 "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du" + 364 "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo" + 365 "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk" + 366 "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc" + 367 "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3" + 368 "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk" + 369 "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH" + 370 "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs" + 371 "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq" + 372 "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg" + 373 "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu" + 374 "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD" + 375 "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH" + 376 "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0" + 377 "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w" + 378 "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf" + 379 "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg" + 380 "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT" + 381 "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB" + 382 "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW" + 383 "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY" + 384 "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0="; 385 386 private String PASSWORD = "android"; 387 388 /** 389 * Loads a keystore from a base64-encoded String. Returns the KeyManager[] 390 * for the result. 391 */ 392 private KeyManager[] getKeyManagers() throws Exception { 393 String keys = (useBKS ? SERVER_KEYS_BKS : SERVER_KEYS_JKS); 394 byte[] bytes = Base64.decode(keys.getBytes()); 395 InputStream inputStream = new ByteArrayInputStream(bytes); 396 397 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 398 keyStore.load(inputStream, PASSWORD.toCharArray()); 399 inputStream.close(); 400 401 String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 402 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm); 403 keyManagerFactory.init(keyStore, PASSWORD.toCharArray()); 404 405 return keyManagerFactory.getKeyManagers(); 406 } 407 408 private SSLServerSocket getSSLServerSocket() throws Exception { 409 SSLContext context = SSLContext.getInstance("TLS"); 410 context.init(getKeyManagers(), null, null); 411 SSLServerSocket sss = (SSLServerSocket) context.getServerSocketFactory() 412 .createServerSocket(); 413 return sss; 414 } 415 416 public void test_creationStressTest() throws Exception { 417 KeyManager[] keyManagers = getKeyManagers(); 418 // Test the default codepath, which uses /dev/urandom. 419 SSLContext sslContext = SSLContext.getInstance("TLS"); 420 sslContext.init(keyManagers, null, null); 421 for (int i = 0; i < 2048; ++i) { 422 sslContext.getServerSocketFactory().createServerSocket().close(); 423 } 424 425 // Test the other codepath, which copies a seed from a byte[]. 426 sslContext.init(keyManagers, null, new SecureRandom()); 427 for (int i = 0; i < 2048; ++i) { 428 sslContext.getServerSocketFactory().createServerSocket().close(); 429 } 430 } 431 } 432