blob: 622b0ec735ac4a042a72e6d1721eb4d538d6d637 [file] [log] [blame]
/*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conscrypt;
import java.io.FileDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
import java.util.Collections;
import java.util.List;
import javax.crypto.spec.GCMParameterSpec;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.StandardConstants;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import sun.security.x509.AlgorithmId;
/**
*
*/
public class Platform {
private static final String TAG = "Conscrypt";
private static Method m_getCurveName;
static {
try {
m_getCurveName = ECParameterSpec.class.getDeclaredMethod("getCurveName");
m_getCurveName.setAccessible(true);
} catch (Exception ignored) {
}
}
public static void setup() {
}
public static FileDescriptor getFileDescriptor(Socket s) {
try {
Field f_impl = Socket.class.getDeclaredField("impl");
f_impl.setAccessible(true);
Object socketImpl = f_impl.get(s);
Class<?> c_socketImpl = Class.forName("java.net.SocketImpl");
Field f_fd = c_socketImpl.getDeclaredField("fd");
f_fd.setAccessible(true);
return (FileDescriptor) f_fd.get(socketImpl);
} catch (Exception e) {
throw new RuntimeException("Can't get FileDescriptor from socket", e);
}
}
public static FileDescriptor getFileDescriptorFromSSLSocket(OpenSSLSocketImpl openSSLSocketImpl) {
return getFileDescriptor(openSSLSocketImpl);
}
public static String getCurveName(ECParameterSpec spec) {
if (m_getCurveName == null) {
return null;
}
try {
return (String) m_getCurveName.invoke(spec);
} catch (Exception e) {
return null;
}
}
public static void setCurveName(ECParameterSpec spec, String curveName) {
// This doesn't appear to be needed.
}
/*
* Call Os.setsockoptTimeval via reflection.
*/
public static void setSocketWriteTimeout(Socket s, long timeoutMillis) throws SocketException {
// TODO: figure this out on the RI
}
public static void setSSLParameters(SSLParameters params, SSLParametersImpl impl,
OpenSSLSocketImpl socket) {
impl.setEndpointIdentificationAlgorithm(params.getEndpointIdentificationAlgorithm());
impl.setUseCipherSuitesOrder(params.getUseCipherSuitesOrder());
List<SNIServerName> serverNames = params.getServerNames();
if (serverNames != null) {
for (SNIServerName serverName : serverNames) {
if (serverName.getType() == StandardConstants.SNI_HOST_NAME) {
socket.setHostname(((SNIHostName) serverName).getAsciiName());
break;
}
}
}
}
public static void getSSLParameters(SSLParameters params, SSLParametersImpl impl,
OpenSSLSocketImpl socket) {
params.setEndpointIdentificationAlgorithm(impl.getEndpointIdentificationAlgorithm());
params.setUseCipherSuitesOrder(impl.getUseCipherSuitesOrder());
if (impl.getUseSni() && AddressUtils.isValidSniHostname(socket.getHostname())) {
params.setServerNames(Collections.<SNIServerName> singletonList(
new SNIHostName(socket.getHostname())));
}
}
/**
* Tries to return a Class reference of one of the supplied class names.
*/
private static Class<?> getClass(String... klasses) {
for (String klass : klasses) {
try {
return Class.forName(klass);
} catch (Exception ignored) {
}
}
return null;
}
public static void setEndpointIdentificationAlgorithm(SSLParameters params,
String endpointIdentificationAlgorithm) {
params.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm);
}
public static String getEndpointIdentificationAlgorithm(SSLParameters params) {
return params.getEndpointIdentificationAlgorithm();
}
public static void checkClientTrusted(X509TrustManager tm, X509Certificate[] chain,
String authType, OpenSSLSocketImpl socket) throws CertificateException {
if (tm instanceof X509ExtendedTrustManager) {
X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm;
x509etm.checkClientTrusted(chain, authType, socket);
} else {
tm.checkClientTrusted(chain, authType);
}
}
public static void checkServerTrusted(X509TrustManager tm, X509Certificate[] chain,
String authType, OpenSSLSocketImpl socket) throws CertificateException {
if (tm instanceof X509ExtendedTrustManager) {
X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm;
x509etm.checkServerTrusted(chain, authType, socket);
} else {
tm.checkServerTrusted(chain, authType);
}
}
public static void checkClientTrusted(X509TrustManager tm, X509Certificate[] chain,
String authType, OpenSSLEngineImpl engine) throws CertificateException {
if (tm instanceof X509ExtendedTrustManager) {
X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm;
x509etm.checkClientTrusted(chain, authType, engine);
} else {
tm.checkClientTrusted(chain, authType);
}
}
public static void checkServerTrusted(X509TrustManager tm, X509Certificate[] chain,
String authType, OpenSSLEngineImpl engine) throws CertificateException {
if (tm instanceof X509ExtendedTrustManager) {
X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) tm;
x509etm.checkServerTrusted(chain, authType, engine);
} else {
tm.checkServerTrusted(chain, authType);
}
}
/**
* Wraps an old AndroidOpenSSL key instance. This is not needed on RI.
*/
public static OpenSSLKey wrapRsaKey(PrivateKey javaKey) {
return null;
}
/**
* Logs to the system EventLog system.
*/
public static void logEvent(String message) {
}
/**
* Returns true if the supplied hostname is an literal IP address.
*/
public static boolean isLiteralIpAddress(String hostname) {
// TODO: any RI API to make this better?
return AddressUtils.isLiteralIpAddress(hostname);
}
/**
* For unbundled versions, SNI is always enabled by default.
*/
public static boolean isSniEnabledByDefault() {
return true;
}
/**
* Currently we don't wrap anything from the RI.
*/
public static SSLSocketFactory wrapSocketFactoryIfNeeded(OpenSSLSocketFactoryImpl factory) {
return factory;
}
/**
* Convert from platform's GCMParameterSpec to our internal version.
*/
public static GCMParameters fromGCMParameterSpec(AlgorithmParameterSpec params) {
if (params instanceof GCMParameterSpec) {
GCMParameterSpec gcmParams = (GCMParameterSpec) params;
return new GCMParameters(gcmParams.getTLen(), gcmParams.getIV());
}
return null;
}
/**
* Creates a platform version of {@code GCMParameterSpec}.
*/
public static AlgorithmParameterSpec toGCMParameterSpec(int tagLenInBits, byte[] iv) {
return new GCMParameterSpec(tagLenInBits, iv);
}
/*
* CloseGuard functions.
*/
public static Object closeGuardGet() {
return null;
}
public static void closeGuardOpen(Object guardObj, String message) {
}
public static void closeGuardClose(Object guardObj) {
}
public static void closeGuardWarnIfOpen(Object guardObj) {
}
/*
* BlockGuard functions.
*/
public static void blockGuardOnNetwork() {
}
/**
* OID to Algorithm Name mapping.
*/
public static String oidToAlgorithmName(String oid) {
try {
return AlgorithmId.get(oid).getName();
} catch (NoSuchAlgorithmException e) {
return oid;
}
}
/*
* Pre-Java-8 backward compatibility.
*/
public static SSLSession wrapSSLSession(OpenSSLSessionImpl sslSession) {
return new OpenSSLExtendedSessionImpl(sslSession);
}
/*
* Pre-Java-7 backward compatibility.
*/
public static String getHostStringFromInetSocketAddress(InetSocketAddress addr) {
return addr.getHostString();
}
}