1/* 2 * Copyright (C) 2013 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 17package libcore.javax.net.ssl; 18 19import junit.framework.Assert; 20import libcore.java.security.StandardNames; 21import java.io.IOException; 22import java.util.Arrays; 23import java.util.Collections; 24import java.util.HashSet; 25import java.util.Set; 26import javax.net.ssl.SSLContext; 27import javax.net.ssl.SSLEngine; 28import javax.net.ssl.SSLParameters; 29import javax.net.ssl.SSLServerSocket; 30import javax.net.ssl.SSLServerSocketFactory; 31import javax.net.ssl.SSLSocket; 32import javax.net.ssl.SSLSocketFactory; 33 34/** 35 * Assertions about the configuration of TLS/SSL primitives. 36 */ 37public class SSLConfigurationAsserts extends Assert { 38 39 /** Hidden constructor to prevent instantiation. */ 40 private SSLConfigurationAsserts() {} 41 42 /** 43 * Asserts that the provided {@link SSLContext} has the expected default configuration, and that 44 * {@link SSLSocketFactory}, {@link SSLServerSocketFactory}, {@link SSLSocket}, 45 * {@link SSLServerSocket} and {@link SSLEngine} instances created from the context match the 46 * configuration. 47 */ 48 public static void assertSSLContextDefaultConfiguration(SSLContext sslContext) 49 throws IOException { 50 SSLParameters defaultParameters = sslContext.getDefaultSSLParameters(); 51 StandardNames.assertSSLContextEnabledProtocols(sslContext.getProtocol(), 52 defaultParameters.getProtocols()); 53 StandardNames.assertDefaultCipherSuites(defaultParameters.getCipherSuites()); 54 assertFalse(defaultParameters.getWantClientAuth()); 55 assertFalse(defaultParameters.getNeedClientAuth()); 56 57 SSLParameters supportedParameters = sslContext.getSupportedSSLParameters(); 58 StandardNames.assertSupportedCipherSuites(supportedParameters.getCipherSuites()); 59 StandardNames.assertSupportedProtocols(supportedParameters.getProtocols()); 60 assertFalse(supportedParameters.getWantClientAuth()); 61 assertFalse(supportedParameters.getNeedClientAuth()); 62 63 assertContainsAll("Unsupported enabled cipher suites", supportedParameters.getCipherSuites(), 64 defaultParameters.getCipherSuites()); 65 assertContainsAll("Unsupported enabled protocols", supportedParameters.getProtocols(), 66 defaultParameters.getProtocols()); 67 68 assertSSLSocketFactoryConfigSameAsSSLContext(sslContext.getSocketFactory(), sslContext); 69 assertSSLServerSocketFactoryConfigSameAsSSLContext(sslContext.getServerSocketFactory(), 70 sslContext); 71 72 SSLEngine sslEngine = sslContext.createSSLEngine(); 73 assertFalse(sslEngine.getUseClientMode()); 74 assertSSLEngineConfigSameAsSSLContext(sslEngine, sslContext); 75 } 76 77 /** 78 * Asserts that the provided {@link SSLSocketFactory} has the expected default configuration and 79 * that {@link SSLSocket} instances created by the factory match the configuration. 80 */ 81 public static void assertSSLSocketFactoryDefaultConfiguration( 82 SSLSocketFactory sslSocketFactory) throws Exception { 83 assertSSLSocketFactoryConfigSameAsSSLContext(sslSocketFactory, 84 SSLContext.getDefault()); 85 } 86 87 /** 88 * Asserts that {@link SSLSocketFactory}'s configuration matches {@code SSLContext}'s 89 * configuration, and that {@link SSLSocket} instances obtained from the factory match this 90 * configuration as well. 91 */ 92 private static void assertSSLSocketFactoryConfigSameAsSSLContext( 93 SSLSocketFactory sslSocketFactory, SSLContext sslContext) throws IOException { 94 assertCipherSuitesEqual(sslContext.getDefaultSSLParameters().getCipherSuites(), 95 sslSocketFactory.getDefaultCipherSuites()); 96 assertCipherSuitesEqual(sslContext.getSupportedSSLParameters().getCipherSuites(), 97 sslSocketFactory.getSupportedCipherSuites()); 98 99 try (SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket()) { 100 assertTrue(sslSocket.getUseClientMode()); 101 assertTrue(sslSocket.getEnableSessionCreation()); 102 assertSSLSocketConfigSameAsSSLContext(sslSocket, sslContext); 103 } 104 } 105 106 /** 107 * Asserts that the provided {@link SSLSocket} has the expected default configuration. 108 */ 109 public static void assertSSLSocketDefaultConfiguration(SSLSocket sslSocket) throws Exception { 110 assertTrue(sslSocket.getUseClientMode()); 111 assertTrue(sslSocket.getEnableSessionCreation()); 112 assertSSLSocketConfigSameAsSSLContext(sslSocket, SSLContext.getDefault()); 113 } 114 115 /** 116 * Asserts that {@link SSLSocket}'s configuration matches {@code SSLContext's} configuration. 117 */ 118 private static void assertSSLSocketConfigSameAsSSLContext(SSLSocket sslSocket, 119 SSLContext sslContext) { 120 assertSSLParametersEqual(sslSocket.getSSLParameters(), sslContext.getDefaultSSLParameters()); 121 assertCipherSuitesEqual(sslSocket.getEnabledCipherSuites(), 122 sslContext.getDefaultSSLParameters().getCipherSuites()); 123 assertProtocolsEqual(sslSocket.getEnabledProtocols(), 124 sslContext.getDefaultSSLParameters().getProtocols()); 125 126 assertCipherSuitesEqual(sslSocket.getSupportedCipherSuites(), 127 sslContext.getSupportedSSLParameters().getCipherSuites()); 128 assertProtocolsEqual(sslSocket.getSupportedProtocols(), 129 sslContext.getSupportedSSLParameters().getProtocols()); 130 } 131 132 /** 133 * Asserts that the provided {@link SSLServerSocketFactory} has the expected default 134 * configuration, and that {@link SSLServerSocket} instances created by the factory match the 135 * configuration. 136 */ 137 public static void assertSSLServerSocketFactoryDefaultConfiguration( 138 SSLServerSocketFactory sslServerSocketFactory) throws Exception { 139 assertSSLServerSocketFactoryConfigSameAsSSLContext(sslServerSocketFactory, 140 SSLContext.getDefault()); 141 } 142 143 /** 144 * Asserts that {@link SSLServerSocketFactory}'s configuration matches {@code SSLContext}'s 145 * configuration, and that {@link SSLServerSocket} instances obtained from the factory match this 146 * configuration as well. 147 */ 148 private static void assertSSLServerSocketFactoryConfigSameAsSSLContext( 149 SSLServerSocketFactory sslServerSocketFactory, SSLContext sslContext) throws IOException { 150 assertCipherSuitesEqual(sslContext.getDefaultSSLParameters().getCipherSuites(), 151 sslServerSocketFactory.getDefaultCipherSuites()); 152 assertCipherSuitesEqual(sslContext.getSupportedSSLParameters().getCipherSuites(), 153 sslServerSocketFactory.getSupportedCipherSuites()); 154 try (SSLServerSocket sslServerSocket = 155 (SSLServerSocket) sslServerSocketFactory.createServerSocket()) { 156 assertFalse(sslServerSocket.getUseClientMode()); 157 assertTrue(sslServerSocket.getEnableSessionCreation()); 158 assertSSLServerSocketConfigSameAsSSLContext(sslServerSocket, sslContext); 159 } 160 } 161 162 /** 163 * Asserts that the provided {@link SSLServerSocket} has the expected default configuration. 164 */ 165 public static void assertSSLServerSocketDefaultConfiguration(SSLServerSocket sslServerSocket) 166 throws Exception { 167 assertFalse(sslServerSocket.getUseClientMode()); 168 assertTrue(sslServerSocket.getEnableSessionCreation()); 169 assertSSLServerSocketConfigSameAsSSLContext(sslServerSocket, SSLContext.getDefault()); 170 // TODO: Check SSLParameters when supported by SSLServerSocket API 171 } 172 173 /** 174 * Asserts that {@link SSLServerSocket}'s configuration matches {@code SSLContext's} 175 * configuration. 176 */ 177 private static void assertSSLServerSocketConfigSameAsSSLContext(SSLServerSocket sslServerSocket, 178 SSLContext sslContext) { 179 assertCipherSuitesEqual(sslServerSocket.getEnabledCipherSuites(), 180 sslContext.getDefaultSSLParameters().getCipherSuites()); 181 assertProtocolsEqual(sslServerSocket.getEnabledProtocols(), 182 sslContext.getDefaultSSLParameters().getProtocols()); 183 184 assertCipherSuitesEqual(sslServerSocket.getSupportedCipherSuites(), 185 sslContext.getSupportedSSLParameters().getCipherSuites()); 186 assertProtocolsEqual(sslServerSocket.getSupportedProtocols(), 187 sslContext.getSupportedSSLParameters().getProtocols()); 188 189 assertEquals(sslServerSocket.getNeedClientAuth(), 190 sslContext.getDefaultSSLParameters().getNeedClientAuth()); 191 assertEquals(sslServerSocket.getWantClientAuth(), 192 sslContext.getDefaultSSLParameters().getWantClientAuth()); 193 } 194 195 /** 196 * Asserts that the provided {@link SSLEngine} has the expected default configuration. 197 */ 198 public static void assertSSLEngineDefaultConfiguration(SSLEngine sslEngine) throws Exception { 199 assertFalse(sslEngine.getUseClientMode()); 200 assertTrue(sslEngine.getEnableSessionCreation()); 201 assertSSLEngineConfigSameAsSSLContext(sslEngine, SSLContext.getDefault()); 202 } 203 204 /** 205 * Asserts that {@link SSLEngine}'s configuration matches {@code SSLContext's} configuration. 206 */ 207 private static void assertSSLEngineConfigSameAsSSLContext(SSLEngine sslEngine, 208 SSLContext sslContext) { 209 assertSSLParametersEqual(sslEngine.getSSLParameters(), sslContext.getDefaultSSLParameters()); 210 assertCipherSuitesEqual(sslEngine.getEnabledCipherSuites(), 211 sslContext.getDefaultSSLParameters().getCipherSuites()); 212 assertProtocolsEqual(sslEngine.getEnabledProtocols(), 213 sslContext.getDefaultSSLParameters().getProtocols()); 214 215 assertCipherSuitesEqual(sslEngine.getSupportedCipherSuites(), 216 sslContext.getSupportedSSLParameters().getCipherSuites()); 217 assertProtocolsEqual(sslEngine.getSupportedProtocols(), 218 sslContext.getSupportedSSLParameters().getProtocols()); 219 } 220 221 private static void assertSSLParametersEqual(SSLParameters expected, SSLParameters actual) { 222 assertCipherSuitesEqual(expected.getCipherSuites(), actual.getCipherSuites()); 223 assertProtocolsEqual(expected.getProtocols(), actual.getProtocols()); 224 assertEquals(expected.getNeedClientAuth(), actual.getNeedClientAuth()); 225 assertEquals(expected.getWantClientAuth(), actual.getWantClientAuth()); 226 } 227 228 private static void assertCipherSuitesEqual(String[] expected, String[] actual) { 229 assertEquals(Arrays.asList(expected), Arrays.asList(actual)); 230 } 231 232 private static void assertProtocolsEqual(String[] expected, String[] actual) { 233 // IMPLEMENTATION NOTE: The order of protocols versions does not matter. Similarly, it only 234 // matters whether a protocol version is present or absent in the array. These arrays are 235 // supposed to represent sets of protocol versions. Thus, we treat them as such. 236 assertEquals(new HashSet<String>(Arrays.asList(expected)), 237 new HashSet<String>(Arrays.asList(actual))); 238 } 239 240 /** 241 * Asserts that the {@code container} contains all the {@code elements}. 242 */ 243 private static void assertContainsAll(String message, String[] container, String[] elements) { 244 Set<String> elementsNotInContainer = new HashSet<String>(Arrays.asList(elements)); 245 elementsNotInContainer.removeAll(Arrays.asList(container)); 246 assertEquals(message, Collections.EMPTY_SET, elementsNotInContainer); 247 } 248} 249