1 /* 2 * Copyright 2014 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 org.conscrypt; 18 19 import java.io.FileDescriptor; 20 import java.lang.reflect.Field; 21 import java.lang.reflect.Method; 22 import java.net.InetAddress; 23 import java.net.InetSocketAddress; 24 import java.net.Socket; 25 import java.net.SocketException; 26 import java.security.InvalidKeyException; 27 import java.security.NoSuchAlgorithmException; 28 import java.security.PrivateKey; 29 import java.security.cert.CertificateException; 30 import java.security.cert.X509Certificate; 31 import java.security.spec.AlgorithmParameterSpec; 32 import java.security.spec.ECParameterSpec; 33 import java.util.Collections; 34 import java.util.List; 35 import javax.crypto.spec.GCMParameterSpec; 36 import javax.net.ssl.SNIHostName; 37 import javax.net.ssl.SNIServerName; 38 import javax.net.ssl.SSLEngine; 39 import javax.net.ssl.SSLParameters; 40 import javax.net.ssl.SSLSession; 41 import javax.net.ssl.SSLSocketFactory; 42 import javax.net.ssl.StandardConstants; 43 import javax.net.ssl.X509ExtendedTrustManager; 44 import javax.net.ssl.X509TrustManager; 45 import sun.security.x509.AlgorithmId; 46 47 /** 48 * 49 */ 50 public class Platform { 51 private static final String TAG = "Conscrypt"; 52 53 private static Method m_getCurveName; 54 static { 55 try { 56 m_getCurveName = ECParameterSpec.class.getDeclaredMethod("getCurveName"); 57 m_getCurveName.setAccessible(true); 58 } catch (Exception ignored) { 59 } 60 } 61 setup()62 public static void setup() { 63 } 64 getFileDescriptor(Socket s)65 public static FileDescriptor getFileDescriptor(Socket s) { 66 try { 67 Field f_impl = Socket.class.getDeclaredField("impl"); 68 f_impl.setAccessible(true); 69 Object socketImpl = f_impl.get(s); 70 Class<?> c_socketImpl = Class.forName("java.net.SocketImpl"); 71 Field f_fd = c_socketImpl.getDeclaredField("fd"); 72 f_fd.setAccessible(true); 73 return (FileDescriptor) f_fd.get(socketImpl); 74 } catch (Exception e) { 75 throw new RuntimeException("Can't get FileDescriptor from socket", e); 76 } 77 } 78 getFileDescriptorFromSSLSocket(OpenSSLSocketImpl openSSLSocketImpl)79 public static FileDescriptor getFileDescriptorFromSSLSocket(OpenSSLSocketImpl openSSLSocketImpl) { 80 return getFileDescriptor(openSSLSocketImpl); 81 } 82 getCurveName(ECParameterSpec spec)83 public static String getCurveName(ECParameterSpec spec) { 84 if (m_getCurveName == null) { 85 return null; 86 } 87 try { 88 return (String) m_getCurveName.invoke(spec); 89 } catch (Exception e) { 90 return null; 91 } 92 } 93 setCurveName(ECParameterSpec spec, String curveName)94 public static void setCurveName(ECParameterSpec spec, String curveName) { 95 // This doesn't appear to be needed. 96 } 97 98 /* 99 * Call Os.setsockoptTimeval via reflection. 100 */ setSocketWriteTimeout(Socket s, long timeoutMillis)101 public static void setSocketWriteTimeout(Socket s, long timeoutMillis) throws SocketException { 102 // TODO: figure this out on the RI 103 } 104 setSSLParameters(SSLParameters params, SSLParametersImpl impl, OpenSSLSocketImpl socket)105 public static void setSSLParameters(SSLParameters params, SSLParametersImpl impl, 106 OpenSSLSocketImpl socket) { 107 impl.setEndpointIdentificationAlgorithm(params.getEndpointIdentificationAlgorithm()); 108 impl.setUseCipherSuitesOrder(params.getUseCipherSuitesOrder()); 109 List<SNIServerName> serverNames = params.getServerNames(); 110 if (serverNames != null) { 111 for (SNIServerName serverName : serverNames) { 112 if (serverName.getType() == StandardConstants.SNI_HOST_NAME) { 113 socket.setHostname(((SNIHostName) serverName).getAsciiName()); 114 break; 115 } 116 } 117 } 118 } 119 getSSLParameters(SSLParameters params, SSLParametersImpl impl, OpenSSLSocketImpl socket)120 public static void getSSLParameters(SSLParameters params, SSLParametersImpl impl, 121 OpenSSLSocketImpl socket) { 122 params.setEndpointIdentificationAlgorithm(impl.getEndpointIdentificationAlgorithm()); 123 params.setUseCipherSuitesOrder(impl.getUseCipherSuitesOrder()); 124 if (impl.getUseSni() && AddressUtils.isValidSniHostname(socket.getHostname())) { 125 params.setServerNames(Collections.<SNIServerName> singletonList( 126 new SNIHostName(socket.getHostname()))); 127 } 128 } 129 130 /** 131 * Tries to return a Class reference of one of the supplied class names. 132 */ getClass(String... klasses)133 private static Class<?> getClass(String... klasses) { 134 for (String klass : klasses) { 135 try { 136 return Class.forName(klass); 137 } catch (Exception ignored) { 138 } 139 } 140 return null; 141 } 142 setEndpointIdentificationAlgorithm(SSLParameters params, String endpointIdentificationAlgorithm)143 public static void setEndpointIdentificationAlgorithm(SSLParameters params, 144 String endpointIdentificationAlgorithm) { 145 params.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm); 146 } 147 getEndpointIdentificationAlgorithm(SSLParameters params)148 public static String getEndpointIdentificationAlgorithm(SSLParameters params) { 149 return params.getEndpointIdentificationAlgorithm(); 150 } 151 checkClientTrusted(X509TrustManager tm, X509Certificate[] chain, String authType, OpenSSLSocketImpl socket)152 public static void checkClientTrusted(X509TrustManager tm, X509Certificate[] chain, 153 String authType, OpenSSLSocketImpl socket) throws CertificateException { 154 if (tm instanceof X509ExtendedTrustManager) { 155 X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm; 156 x509etm.checkClientTrusted(chain, authType, socket); 157 } else { 158 tm.checkClientTrusted(chain, authType); 159 } 160 } 161 checkServerTrusted(X509TrustManager tm, X509Certificate[] chain, String authType, OpenSSLSocketImpl socket)162 public static void checkServerTrusted(X509TrustManager tm, X509Certificate[] chain, 163 String authType, OpenSSLSocketImpl socket) throws CertificateException { 164 if (tm instanceof X509ExtendedTrustManager) { 165 X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm; 166 x509etm.checkServerTrusted(chain, authType, socket); 167 } else { 168 tm.checkServerTrusted(chain, authType); 169 } 170 } 171 checkClientTrusted(X509TrustManager tm, X509Certificate[] chain, String authType, OpenSSLEngineImpl engine)172 public static void checkClientTrusted(X509TrustManager tm, X509Certificate[] chain, 173 String authType, OpenSSLEngineImpl engine) throws CertificateException { 174 if (tm instanceof X509ExtendedTrustManager) { 175 X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm; 176 x509etm.checkClientTrusted(chain, authType, engine); 177 } else { 178 tm.checkClientTrusted(chain, authType); 179 } 180 } 181 checkServerTrusted(X509TrustManager tm, X509Certificate[] chain, String authType, OpenSSLEngineImpl engine)182 public static void checkServerTrusted(X509TrustManager tm, X509Certificate[] chain, 183 String authType, OpenSSLEngineImpl engine) throws CertificateException { 184 if (tm instanceof X509ExtendedTrustManager) { 185 X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm; 186 x509etm.checkServerTrusted(chain, authType, engine); 187 } else { 188 tm.checkServerTrusted(chain, authType); 189 } 190 } 191 192 /** 193 * Wraps an old AndroidOpenSSL key instance. This is not needed on RI. 194 */ wrapRsaKey(PrivateKey javaKey)195 public static OpenSSLKey wrapRsaKey(PrivateKey javaKey) { 196 return null; 197 } 198 199 /** 200 * Logs to the system EventLog system. 201 */ logEvent(String message)202 public static void logEvent(String message) { 203 } 204 205 /** 206 * Returns true if the supplied hostname is an literal IP address. 207 */ isLiteralIpAddress(String hostname)208 public static boolean isLiteralIpAddress(String hostname) { 209 // TODO: any RI API to make this better? 210 return AddressUtils.isLiteralIpAddress(hostname); 211 } 212 213 /** 214 * For unbundled versions, SNI is always enabled by default. 215 */ isSniEnabledByDefault()216 public static boolean isSniEnabledByDefault() { 217 return true; 218 } 219 220 /** 221 * Currently we don't wrap anything from the RI. 222 */ wrapSocketFactoryIfNeeded(OpenSSLSocketFactoryImpl factory)223 public static SSLSocketFactory wrapSocketFactoryIfNeeded(OpenSSLSocketFactoryImpl factory) { 224 return factory; 225 } 226 227 /** 228 * Convert from platform's GCMParameterSpec to our internal version. 229 */ fromGCMParameterSpec(AlgorithmParameterSpec params)230 public static GCMParameters fromGCMParameterSpec(AlgorithmParameterSpec params) { 231 if (params instanceof GCMParameterSpec) { 232 GCMParameterSpec gcmParams = (GCMParameterSpec) params; 233 return new GCMParameters(gcmParams.getTLen(), gcmParams.getIV()); 234 } 235 return null; 236 } 237 238 /** 239 * Creates a platform version of {@code GCMParameterSpec}. 240 */ toGCMParameterSpec(int tagLenInBits, byte[] iv)241 public static AlgorithmParameterSpec toGCMParameterSpec(int tagLenInBits, byte[] iv) { 242 return new GCMParameterSpec(tagLenInBits, iv); 243 } 244 245 /* 246 * CloseGuard functions. 247 */ 248 closeGuardGet()249 public static Object closeGuardGet() { 250 return null; 251 } 252 closeGuardOpen(Object guardObj, String message)253 public static void closeGuardOpen(Object guardObj, String message) { 254 } 255 closeGuardClose(Object guardObj)256 public static void closeGuardClose(Object guardObj) { 257 } 258 closeGuardWarnIfOpen(Object guardObj)259 public static void closeGuardWarnIfOpen(Object guardObj) { 260 } 261 262 /* 263 * BlockGuard functions. 264 */ 265 blockGuardOnNetwork()266 public static void blockGuardOnNetwork() { 267 } 268 269 /** 270 * OID to Algorithm Name mapping. 271 */ oidToAlgorithmName(String oid)272 public static String oidToAlgorithmName(String oid) { 273 try { 274 return AlgorithmId.get(oid).getName(); 275 } catch (NoSuchAlgorithmException e) { 276 return oid; 277 } 278 } 279 280 /* 281 * Pre-Java-8 backward compatibility. 282 */ 283 wrapSSLSession(OpenSSLSessionImpl sslSession)284 public static SSLSession wrapSSLSession(OpenSSLSessionImpl sslSession) { 285 return new OpenSSLExtendedSessionImpl(sslSession); 286 } 287 288 /* 289 * Pre-Java-7 backward compatibility. 290 */ 291 getHostStringFromInetSocketAddress(InetSocketAddress addr)292 public static String getHostStringFromInetSocketAddress(InetSocketAddress addr) { 293 return addr.getHostString(); 294 } 295 } 296