OpenSSLSocketImpl.java revision e247367fbd5d5b0451c3b3e61e6dba37f27d49e1
108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/*
208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * you may not use this file except in compliance with the License.
608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * You may obtain a copy of the License at
708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * See the License for the specific language governing permissions and
1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * limitations under the License.
1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
19ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard;
2008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException;
2108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream;
2208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream;
2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress;
2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket;
2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException;
2698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey;
2798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom;
281f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException;
2908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException;
3008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.X509Certificate;
3108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList;
32f7923f6b146ae1a750fb733cf03f9db27e68b5dacrazybobimport java.util.concurrent.atomic.AtomicInteger;
3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.logging.Logger;
3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
3508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException;
372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException;
3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession;
3998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal;
4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl;
4108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/**
430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p>
4508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere
46f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * later, for example in the package.html or a separate reference document.
470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p>
480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include:
490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul>
500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout
510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>compression methods
520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets
530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication
540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul>
5508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
56f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl
57f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        extends javax.net.ssl.SSLSocket
5898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        implements NativeCrypto.SSLHandshakeCallbacks {
59f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private int sslNativePointer;
6008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private InputStream is;
6108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private OutputStream os;
6208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private final Object handshakeLock = new Object();
63f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private final Object readLock = new Object();
64f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private final Object writeLock = new Object();
65cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    private SSLParametersImpl sslParameters;
662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private String[] enabledProtocols;
672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private String[] enabledCipherSuites;
680b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    private String[] enabledCompressionMethods;
690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    private boolean useSessionTickets;
700b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    private String hostname;
7108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private OpenSSLSessionImpl sslSession;
7208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private Socket socket;
7308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private boolean autoClose;
7408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private boolean handshakeStarted = false;
752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * Not set to true until the update from native that tells us the
782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * full handshake is complete, since SSL_do_handshake can return
792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * before the handshake is completely done due to
802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * handshake_cutthrough support.
812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private boolean handshakeCompleted = false;
832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
8408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private ArrayList<HandshakeCompletedListener> listeners;
8508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private int timeout = 0;
86331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // BEGIN android-added
87331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    private int handshakeTimeout = -1;  // -1 = same as timeout; 0 = infinite
88331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // END android-added
896e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom    private String wrappedHost;
906e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom    private int wrappedPort;
9108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
92f7923f6b146ae1a750fb733cf03f9db27e68b5dacrazybob    private static final AtomicInteger instanceCount = new AtomicInteger(0);
9308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
9408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public static int getInstanceCount() {
95f7923f6b146ae1a750fb733cf03f9db27e68b5dacrazybob        return instanceCount.get();
9608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
9708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
9808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private static void updateInstanceCount(int amount) {
99f7923f6b146ae1a750fb733cf03f9db27e68b5dacrazybob        instanceCount.addAndGet(amount);
10008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
10108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
10208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
10308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Class constructor with 1 parameter
10408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
10508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param sslParameters Parameters for the SSL
10608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            context
10708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
10808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
109cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException {
11008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super();
111f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
11208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
1152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl
1162828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     *
1172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @param sslParameters Parameters for the SSL
1182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     *            context
1192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @throws IOException if network fails
1202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
121cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters,
1222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                                String[] enabledProtocols,
1230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                                String[] enabledCipherSuites,
1240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                                String[] enabledCompressionMethods) throws IOException {
1252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        super();
1260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods);
1272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
1282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
1292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
13008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Class constructor with 3 parameters
13108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
13208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
13308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws java.net.UnknownHostException host not defined
13408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
135cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters)
13608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throws IOException {
13708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(host, port);
138f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
13908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
14008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
14108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
14208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Class constructor with 3 parameters: 1st is InetAddress
14308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
14408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
14508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws java.net.UnknownHostException host not defined
14608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
147cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters)
14808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throws IOException {
14908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port);
150f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
15108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
15208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
15308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
15408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
15508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Class constructor with 5 parameters: 1st is host
15608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
15708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
15808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws java.net.UnknownHostException host not defined
15908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
160c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom    protected OpenSSLSocketImpl(String host, int port,
161c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
162cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom                                SSLParametersImpl sslParameters)
16308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throws IOException {
16408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(host, port, clientAddress, clientPort);
165f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
16608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
16708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
16808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
16908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Class constructor with 5 parameters: 1st is InetAddress
17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
17108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
17208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws java.net.UnknownHostException host not defined
17308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
17408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
175c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
176cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom                                SSLParametersImpl sslParameters)
17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throws IOException {
17808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port, clientAddress, clientPort);
179f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
18108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
18208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
18308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Constructor with 5 parameters: 1st is socket. Enhances an existing socket
1846e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom     * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor.
18508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
18608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IOException if network fails
18708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(Socket socket, String host, int port,
189cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom            boolean autoClose, SSLParametersImpl sslParameters) throws IOException {
19008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super();
19108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.socket = socket;
19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.timeout = socket.getSoTimeout();
1936e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom        this.wrappedHost = host;
1946e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom        this.wrappedPort = port;
19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.autoClose = autoClose;
196f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        init(sslParameters);
197f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
198f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
199f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    /**
200f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     * Initialize the SSL socket and set the certificates for the
201f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     * future handshaking.
202f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     */
203cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    private void init(SSLParametersImpl sslParameters) throws IOException {
2042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        init(sslParameters,
2052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom             NativeCrypto.getSupportedProtocols(),
2060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom             NativeCrypto.getDefaultCipherSuites(),
2070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom             NativeCrypto.getDefaultCompressionMethods());
208f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
209f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
210f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    /**
2112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * Initialize the SSL socket and set the certificates for the
2122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * future handshaking.
213f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     */
214cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    private void init(SSLParametersImpl sslParameters,
2152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                      String[] enabledProtocols,
2160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                      String[] enabledCipherSuites,
2170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                      String[] enabledCompressionMethods) throws IOException {
2182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        this.sslParameters = sslParameters;
2192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        this.enabledProtocols = enabledProtocols;
2202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        this.enabledCipherSuites = enabledCipherSuites;
2210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        this.enabledCompressionMethods = enabledCompressionMethods;
22208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        updateInstanceCount(1);
22308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
22408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
22508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
22608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Gets the suitable session reference from the session cache container.
22708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
22808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return OpenSSLSessionImpl
22908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
2302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) {
23108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (super.getInetAddress() == null ||
23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                super.getInetAddress().getHostAddress() == null ||
23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                super.getInetAddress().getHostName() == null) {
23408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
23661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(
23708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                super.getInetAddress().getHostName(),
23808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                super.getPort());
23961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (session == null) {
24061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return null;
24161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
24261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
24361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        String protocol = session.getProtocol();
24461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        boolean protocolFound = false;
24561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        for (String enabledProtocol : enabledProtocols) {
24661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            if (protocol.equals(enabledProtocol)) {
24761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                protocolFound = true;
24861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                break;
24961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
25061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
25161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (!protocolFound) {
25261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return null;
25361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
25461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
25561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        String cipherSuite = session.getCipherSuite();
25661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        boolean cipherSuiteFound = false;
25761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        for (String enabledCipherSuite : enabledCipherSuites) {
25861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            if (cipherSuite.equals(enabledCipherSuite)) {
25961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                cipherSuiteFound = true;
26061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                break;
26161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
26261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (!cipherSuiteFound) {
26461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return null;
26561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
2670b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        String compressionMethod = session.getCompressionMethod();
2680b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        boolean compressionMethodFound = false;
2690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        for (String enabledCompressionMethod : enabledCompressionMethods) {
2700b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            if (compressionMethod.equals(enabledCompressionMethod)) {
2710b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                compressionMethodFound = true;
2720b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom                break;
2730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            }
2740b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        }
2750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        if (!compressionMethodFound) {
2760b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            return null;
2770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        }
2780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
27961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        return session;
28008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
28108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
28208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
28308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Ensures that logger is lazily loaded. The outer class seems to load
28408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * before logging is ready.
28508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
28608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    static class LoggerHolder {
287f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName());
28808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
28908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
29008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
29108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Starts a TLS/SSL handshake on this connection using some native methods
29208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * from the OpenSSL library. It can negotiate new encryption keys, change
29308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * cipher suites, or initiate a new session. The certificate chain is
29408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * verified if the correspondent property in java.Security is set. All
295f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     * listeners are notified at the end of the TLS/SSL handshake.
29608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
29708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if network fails
29808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
2990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
3002828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    public void startHandshake() throws IOException {
3012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        startHandshake(true);
3022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
3032828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
305a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom     * Checks whether the socket is closed, and throws an exception.
306a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom     *
307a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom     * @throws SocketException
308a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom     *             if the socket is closed.
309a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom     */
310a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    private void checkOpen() throws SocketException {
311a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        if (isClosed()) {
312a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            throw new SocketException("Socket is closed");
313a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        }
314a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    }
315a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom
316a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    /**
3172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * Perform the handshake
3182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @param full If true, disable handshake cutthrough for a fully synchronous handshake
3192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
3202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    public synchronized void startHandshake(boolean full) throws IOException {
321a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
32208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        synchronized (handshakeLock) {
32308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (!handshakeStarted) {
32408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                handshakeStarted = true;
32508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            } else {
32608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
32708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
32808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
32908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
33098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // note that this modifies the global seed, not something specific to the connection
33198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
33298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
33398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        if (secureRandom == null) {
33498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
33598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        } else {
33698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
33798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
33898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
33998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final boolean client = sslParameters.getUseClientMode();
34098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
34198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final int sslCtxNativePointer = (client) ?
34298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            sslParameters.getClientSessionContext().sslCtxNativePointer :
34398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            sslParameters.getServerSessionContext().sslCtxNativePointer;
34498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
34598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        this.sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
34698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
34798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // setup server certificates and private keys.
34898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // clients will receive a call back to request certificates.
34998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        if (!client) {
35098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            for (String keyType : NativeCrypto.KEY_TYPES) {
351f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                try {
352f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType,
353f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                                                                                   null,
354f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                                                                                   this));
355f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                } catch (CertificateEncodingException e) {
356f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    throw new IOException(e);
357f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                }
35898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            }
35998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
36098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
3612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols);
3622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites);
3630b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        if (enabledCompressionMethods.length != 0) {
3640b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            NativeCrypto.setEnabledCompressionMethods(sslNativePointer, enabledCompressionMethods);
3650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        }
3660b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        if (useSessionTickets) {
3670b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET);
3680b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        }
3690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        if (hostname != null) {
3700b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom            NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname);
3710b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        }
3722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        boolean enableSessionCreation = sslParameters.getEnableSessionCreation();
3742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (!enableSessionCreation) {
3752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer,
3762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                                                          enableSessionCreation);
3772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
3782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        AbstractSessionContext sessionContext;
3802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        OpenSSLSessionImpl session;
3812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (client) {
3822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // look for client session to reuse
3832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext();
3842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            sessionContext = clientSessionContext;
3852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            session = getCachedClientSession(clientSessionContext);
3862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (session != null) {
3872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                NativeCrypto.SSL_set_session(sslNativePointer,  session.sslSessionNativePointer);
3882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
3892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } else {
3902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            sessionContext = sslParameters.getServerSessionContext();
3912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            session = null;
3922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
3932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // setup peer certificate verification
3952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (client) {
39698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            // TODO support for anonymous cipher would require us to
39798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            // conditionally use SSL_VERIFY_NONE
3982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } else {
3992828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // needing client auth takes priority...
400f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            boolean certRequested = false;
4012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (sslParameters.getNeedClientAuth()) {
4022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                NativeCrypto.SSL_set_verify(sslNativePointer,
403f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                                            NativeCrypto.SSL_VERIFY_PEER
404f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                                            | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
405f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                certRequested = true;
4062828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // ... over just wanting it...
4072828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            } else if (sslParameters.getWantClientAuth()) {
4082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                NativeCrypto.SSL_set_verify(sslNativePointer,
40956f7ba2c845a74b0f6d1ec662b36776fa636dd67Brian Carlstrom                                            NativeCrypto.SSL_VERIFY_PEER);
410f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                certRequested = true;
4112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // ... and it defaults properly so we don't need call SSL_set_verify in the common case.
412f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            } else {
413f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                certRequested = false;
414f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
41598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom
416f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (certRequested) {
417f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                X509Certificate[] issuers = sslParameters.getTrustManager().getAcceptedIssuers();
418f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                if (issuers != null) {
419f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    byte[][] issuersBytes;
420f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    try {
421f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                        issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers);
422f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    } catch (CertificateEncodingException e) {
423f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                        throw new IOException("Problem encoding principals", e);
424f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    }
425f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                    NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes);
426f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                }
427f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
4282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
4292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
4302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (client && full) {
4312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // we want to do a full synchronous handshake, so turn off cutthrough
43298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            NativeCrypto.SSL_clear_mode(sslNativePointer,
43398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                                        NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH);
434f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
435f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
436f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // BEGIN android-added
437f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // Temporarily use a different timeout for the handshake process
438f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        int savedTimeout = timeout;
439f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (handshakeTimeout >= 0) {
440f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            setSoTimeout(handshakeTimeout);
441f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
442f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // END android-added
443f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
4442828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
445f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        Socket socket = this.socket != null ? this.socket : this;
4462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        int sslSessionNativePointer;
4472828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        try {
44898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            sslSessionNativePointer
44998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                = NativeCrypto.SSL_do_handshake(sslNativePointer, socket, this, timeout, client);
4502828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (CertificateException e) {
4512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw new SSLPeerUnverifiedException(e.getMessage());
4522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
453743b57452909b1734068f9bd22f87f45d48fe87bBrian Carlstrom        byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
4542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId);
4552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (sslSession != null) {
45661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            sslSession.lastAccessedTime = System.currentTimeMillis();
457f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            LoggerHolder.logger.fine("Reused cached session for "
4582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                                     + getInetAddress() + ".");
459743b57452909b1734068f9bd22f87f45d48fe87bBrian Carlstrom            NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
46008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } else {
4612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (!enableSessionCreation) {
4622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled
4632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                throw new IllegalStateException("SSL Session may not be created");
4642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
465e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            X509Certificate[] localCertificates
466e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                    = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer));
467e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            X509Certificate[] peerCertificates
468e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                    = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer));
4696e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom            if (wrappedHost == null) {
470e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer,
471e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                                                    localCertificates, peerCertificates,
472f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    super.getInetAddress().getHostName(),
473f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    super.getPort(), sessionContext);
474f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            } else  {
475e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer,
476e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                                                    localCertificates, peerCertificates,
4776e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom                                                    wrappedHost, wrappedPort,
478f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    sessionContext);
479f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            }
480c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom            // if not, putSession later in handshakeCompleted() callback
4812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (handshakeCompleted) {
482f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                sessionContext.putSession(sslSession);
483331900211d05cd282141a3a50cb1db626f418b2cDan Egnor            }
4842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            LoggerHolder.logger.fine("Created new session for "
4852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                                     + getInetAddress().getHostName() + ".");
48608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
48708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
488f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // BEGIN android-added
489f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // Restore the original timeout now that the handshake is complete
490f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (handshakeTimeout >= 0) {
491f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            setSoTimeout(savedTimeout);
492f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
493f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // END android-added
494f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
495c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom        // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
4962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (handshakeCompleted) {
4972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            notifyHandshakeCompletedListeners();
49808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
499e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom    }
50008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
501e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom    /**
502e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom     * Return a possibly null array of X509Certificates given the
503e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom     * possibly null array of DER encoded bytes.
504e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom     */
505e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom    private static final X509Certificate[] createCertChain(byte[][] certificatesBytes) {
506e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        if (certificatesBytes == null) {
507e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            return null;
508e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        }
509e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        X509Certificate[] certificates = new X509Certificate[certificatesBytes.length];
510e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        for (int i = 0; i < certificatesBytes.length; i++) {
511e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            try {
512e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                certificates[i] = new X509CertImpl(certificatesBytes[i]);
513e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            } catch (IOException e) {
514e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                return null;
515e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            }
516e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        }
517e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        return certificates;
5182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
51908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
520f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom    private void setCertificate(String alias) throws CertificateEncodingException, SSLException {
52198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        if (alias == null) {
52298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            return;
52398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
52498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
52598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias);
5261f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom        byte[] privateKeyBytes = privateKey.getEncoded();
52798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
52898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
52998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias);
530f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
53198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
53298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
53398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // checks the last installed private key and certificate,
53498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // so need to do this once per loop iteration
53598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_check_private_key(sslNativePointer);
53698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
53798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
53898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    /**
53998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
54098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * invoked via JNI from client_cert_cb
54198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     */
54298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
543f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            throws CertificateEncodingException, SSLException {
54498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom
54598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        String[] keyTypes = new String[keyTypeBytes.length];
54698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        for (int i = 0; i < keyTypeBytes.length; i++) {
54798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
54898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        }
54998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom
55098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        X500Principal[] issuers;
55198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        if (asn1DerEncodedPrincipals == null) {
55298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            issuers = null;
55398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        } else {
55498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            issuers = new X500Principal[asn1DerEncodedPrincipals.length];
55598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) {
55698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom                issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]);
55798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            }
55898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        }
55998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this));
56098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
56198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
56208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
56398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
5642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * invoked via JNI from info_callback
56508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
5662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    public void handshakeCompleted() {
5672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        handshakeCompleted = true;
56808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // If sslSession is null, the handshake was completed during
5702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // the call to NativeCrypto.SSL_do_handshake and not during a
5712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // later read operation. That means we do not need to fixup
5722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // the SSLSession and session cache or notify
5732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // HandshakeCompletedListeners, it will be done in
5742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // startHandshake.
5752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (sslSession == null) {
5762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            return;
5772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
57808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // reset session id from the native pointer and update the
5802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // appropriate cache.
5812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        sslSession.resetId();
5822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        AbstractSessionContext sessionContext =
5832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            (sslParameters.getUseClientMode())
5842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            ? sslParameters.getClientSessionContext()
5852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                : sslParameters.getServerSessionContext();
58608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sessionContext.putSession(sslSession);
5872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // let listeners know we are finally done
5892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        notifyHandshakeCompletedListeners();
5902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
5912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
5932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
5942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // notify the listeners
5952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            HandshakeCompletedEvent event =
5962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
5972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
5982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                try {
5992828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                    listener.handshakeCompleted(event);
6002828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                } catch (RuntimeException e) {
601371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // The RI runs the handlers in a separate thread,
602371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // which we do not. But we try to preserve their
603371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // behavior of logging a problem and not killing
604371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // the handshaking thread just because a listener
605371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // has a problem.
606371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    Thread thread = Thread.currentThread();
607371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
6082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                }
6092828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
6102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
61108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
61208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
61308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
61498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
615f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
61698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom     * @param bytes An array of ASN.1 DER encoded certficates
6172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @param authMethod auth algorithm name
61808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
6192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @throws CertificateException if the certificate is untrusted
62008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
62108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @SuppressWarnings("unused")
62298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    public void verifyCertificateChain(byte[][] bytes, String authMethod)
62398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            throws CertificateException {
62408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
625371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            if (bytes == null || bytes.length == 0) {
626371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                throw new SSLException("Peer sent no certificate");
627371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            }
6282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
6292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (int i = 0; i < bytes.length; i++) {
63008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                peerCertificateChain[i] =
63198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                    new X509CertImpl(
63298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                        javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
63308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
6342828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
6352828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (client) {
63698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain,
63798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                                                                   authMethod);
6382828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            } else {
63998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain,
64098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                                                                   authMethod);
64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
6422828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
6432828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (CertificateException e) {
6442828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw e;
6452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (Exception e) {
6462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw new RuntimeException(e);
64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
64808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns an input stream for this SSL socket using native calls to the
65208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * OpenSSL library.
65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return: an input stream for reading bytes from this socket.
65508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws: <code>IOException</code> if an I/O error occurs when creating
65608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *          the input stream, the socket is closed, the socket is not
65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *          connected, or the socket input has been shutdown.
65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
6590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public InputStream getInputStream() throws IOException {
661a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
662f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        synchronized (this) {
66308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (is == null) {
66408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                is = new SSLInputStream();
66508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
66608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
66708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return is;
66808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
66908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
67008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
67108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
67208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns an output stream for this SSL socket using native calls to the
67308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * OpenSSL library.
67408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
67508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an output stream for writing bytes to this socket.
67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if an I/O error occurs when creating
67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             the output stream, or no connection to the socket exists.
67808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
6790b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public OutputStream getOutputStream() throws IOException {
681a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
682f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        synchronized (this) {
68308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (os == null) {
68408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                os = new SSLOutputStream();
68508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
68608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
68708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return os;
68808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
68908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
69008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
6922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * This method is not supported for this SSLSocket implementation
6932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * because reading from an SSLSocket may involve writing to the
6942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * network.
6952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
6960b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void shutdownInput() throws IOException {
6982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        throw new UnsupportedOperationException();
69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
70008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
7012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
7022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * This method is not supported for this SSLSocket implementation
7032828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * because writing to an SSLSocket may involve reading from the
7042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * network.
7052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
7060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void shutdownOutput() throws IOException {
7082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        throw new UnsupportedOperationException();
70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
71108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides input data stream functionality
71308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * read data received via SSL protocol.
71508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
71608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLInputStream extends InputStream {
71708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        SSLInputStream() throws IOException {
71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /**
71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /* Note: When startHandshake() throws an exception, no
72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             * SSLInputStream object will be created.
72108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             */
7222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
72308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
72408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
72508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
72608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
72708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * this operation can block until the data will be
72808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * available.
72908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @return read value.
73008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @throws <code>IOException</code>
73108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
73308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read() throws IOException {
734a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
735ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
736f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
73758a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                return NativeCrypto.SSL_read_byte(sslNativePointer, timeout);
73808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
73908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
74008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
74108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
74208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
74308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
74408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7450b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
74608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read(byte[] b, int off, int len) throws IOException {
747a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
748ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
749f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (b == null) {
750f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new NullPointerException("b == null");
751f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
752f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if ((len | off) < 0 || len > b.length - off) {
753f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new IndexOutOfBoundsException();
754f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
755f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (0 == len) {
756f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                return 0;
757f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
758f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
75958a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                return NativeCrypto.SSL_read(sslNativePointer, b, off, len, timeout);
76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
76308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
76408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides output data stream functionality
76608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * write data according to the encryption parameters given in SSL context.
76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLOutputStream extends OutputStream {
77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        SSLOutputStream() throws IOException {
77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /**
77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /* Note: When startHandshake() throws an exception, no
773f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom             * SSLOutputStream object will be created.
77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             */
7752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
77908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(int)
78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
78308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public void write(int b) throws IOException {
784a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
785ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
786f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
78758a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                NativeCrypto.SSL_write_byte(sslNativePointer, b);
78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
79108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
79208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7950b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
79608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public void write(byte[] b, int start, int len) throws IOException {
797a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
798ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
799f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (b == null) {
800f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new NullPointerException("b == null");
801f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
802f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if ((len | start) < 0 || len > b.length - start) {
803f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new IndexOutOfBoundsException();
804f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
805f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (len == 0) {
806f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                return;
807f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
808f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
80958a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                NativeCrypto.SSL_write(sslNativePointer, b, start, len);
81008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
81108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
81208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
81308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
81408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
81508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
81608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The SSL session used by this connection is returned. The SSL session
81708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * determines which cipher suite should be used by all connections within
81808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * that session and which identities have the session's client and server.
81908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method starts the SSL handshake.
82008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return the SSLSession.
82108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if the handshake fails
82208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
82408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public SSLSession getSession() {
825e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        if (sslSession == null) {
826e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            try {
827e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                startHandshake(true);
828e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            } catch (IOException e) {
829e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom
830e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // return an invalid session with
831e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
832e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                return SSLSessionImpl.NULL_SESSION;
833e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            }
83408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
83508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslSession;
83608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
83708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
83808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
83908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Registers a listener to be notified that a SSL handshake
84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * was successfully completed on this connection.
84108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IllegalArgumentException</code> if listener is null.
84208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
84408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void addHandshakeCompletedListener(
84508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
84608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
84708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
84808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
84908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
85008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            listeners = new ArrayList();
85108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
85208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        listeners.add(listener);
85308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
85408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
85508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
85608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The method removes a registered listener.
85708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException if listener is null or not registered
85808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
86008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void removeHandshakeCompletedListener(
86108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
86208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
86308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
86508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
86908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!listeners.remove(listener)) {
87008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
87308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
87408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
87508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if new SSL sessions may be established by this socket.
87708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
87808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if the session may be created; false if a session already
87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *         exists and must be resumed.
88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
88208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getEnableSessionCreation() {
88308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getEnableSessionCreation();
88408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
88508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
88608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
88708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Set a flag for the socket to inhibit or to allow the creation of a new
88808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * SSL sessions. If the flag is set to false, and there are no actual
88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * sessions to resume, then there will be no successful handshaking.
89008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
89108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param flag true if session may be created; false
89208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            if a session already exists and must be resumed.
89308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8940b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
89508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
89608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
89708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
89808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
89908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
90008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the cipher suites which could be used by the SSL connection
90108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * are returned.
90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of cipher suite names
90308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9040b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
90508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getSupportedCipherSuites() {
906f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
90708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
90808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
90908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
91008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the cipher suites that are in use in the actual the SSL
91108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection are returned.
91208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of cipher suite names
91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
91608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getEnabledCipherSuites() {
9172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        return enabledCipherSuites.clone();
91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
92008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
92108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method enables the cipher suites listed by
92208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * getSupportedCipherSuites().
92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param suites names of all the cipher suites to
92508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            put on use
92608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException when one or more of the
92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             ciphers in array suites are not supported, or when the array
92808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             is null.
92908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
93108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
9322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites);
93308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
93408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
93508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
93608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the protocols' versions that may be used on this SSL
93708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection.
93808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of protocols names
93908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
94108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getSupportedProtocols() {
942f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
94308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
94408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
94508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
94608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the protocols' versions that are in use on this SSL
94708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection.
948f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
94908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of protocols names
95008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
95108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @Override
95208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getEnabledProtocols() {
9532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        return enabledProtocols.clone();
95408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
95508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
95608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
95708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method enables the protocols' versions listed by
95808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * getSupportedProtocols().
959f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
9600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param protocols The names of all the protocols to allow
961f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
96208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException when one or more of the names in the
96308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             array are not supported, or when the array is null.
96408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @Override
9660b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setEnabledProtocols(String[] protocols) {
9672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols);
96808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
96908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
97008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
9710b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * The names of the compression methods that may be used on this SSL
9720b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * connection.
9730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return an array of compression methods
9740b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String[] getSupportedCompressionMethods() {
9760b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return NativeCrypto.getSupportedCompressionMethods();
9770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9790b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9800b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * The names of the compression methods versions that are in use
9810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * on this SSL connection.
9820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9830b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return an array of compression methods
9840b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9850b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String[] getEnabledCompressionMethods() {
9860b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return enabledCompressionMethods.clone();
9870b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9890b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9900b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables the compression method listed by
9910b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * getSupportedCompressionMethods().
9920b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9930b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param methods The names of all the compression methods to allow
9940b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9950b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @throws IllegalArgumentException when one or more of the names in the
9960b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *             array are not supported, or when the array is null.
9970b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9980b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setEnabledCompressionMethods (String[] methods) {
9990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods);
10000b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10010b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10020b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables session ticket support.
10040b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10050b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param useSessionTickets True to enable session tickets
10060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
10080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        this.useSessionTickets = useSessionTickets;
10090b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method gives true back if the SSL socket is set to client mode.
10130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return true if the socket should do the handshaking as client.
10150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public boolean getUseSessionTickets() {
10170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return useSessionTickets;
10180b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables Server Name Indication
10220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
10240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10250b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHostname(String hostname) {
10260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        this.hostname = hostname;
10270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10290b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method returns the current SNI hostname
10310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return a host name if SNI is enabled, or null otherwise
10330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String getHostname() {
10350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return hostname;
10360b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
103908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method gives true back if the SSL socket is set to client mode.
104008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
104108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if the socket should do the handshaking as client.
104208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
104308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getUseClientMode() {
104408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getUseClientMode();
104508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
104608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
104708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
104808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method set the actual SSL socket to client mode.
104908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
105008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param mode true if the socket starts in client
105108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            mode
105208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException if mode changes during
105308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             handshake.
105408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
10560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseClientMode(boolean mode) {
105708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (handshakeStarted) {
105808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
105908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
106008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
106108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setUseClientMode(mode);
106208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
106308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
106408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
106508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if the SSL socket requests client's authentication. Relevant
106608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * only for server sockets!
106708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
106808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if client authentication is desired, false if not.
106908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10700b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
107108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getWantClientAuth() {
107208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getWantClientAuth();
107308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
107408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
107508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
107608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if the SSL socket needs client's authentication. Relevant
107708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * only for server sockets!
107808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
107908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if client authentication is desired, false if not.
108008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
108208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getNeedClientAuth() {
108308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getNeedClientAuth();
108408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
108508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
108608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
108708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
108808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * server sockets!
108908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
109008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param need true if client authentication is
109108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            desired, false if not.
109208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10930b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
109408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setNeedClientAuth(boolean need) {
109508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setNeedClientAuth(need);
109608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
109708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
109808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
109908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
110008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * server sockets! Notice that in contrast to setNeedClientAuth(..) this
110108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * method will continue the negotiation if the client decide not to send
110208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * authentication credentials.
110308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
110408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param want true if client authentication is
110508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            desired, false if not.
110608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
110808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setWantClientAuth(boolean want) {
110908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setWantClientAuth(want);
111008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
111108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
111208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
111308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method is not supported for SSLSocket implementation.
111408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
111608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void sendUrgentData(int data) throws IOException {
111708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throw new SocketException(
111808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                "Method sendUrgentData() is not supported.");
111908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
112008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
112108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
112208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method is not supported for SSLSocket implementation.
112308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
112508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setOOBInline(boolean on) throws SocketException {
112608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throw new SocketException(
112708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                "Methods sendUrgentData, setOOBInline are not supported.");
112808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
112908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
113008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
113108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
113208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * in milliseconds. The read operation will block indefinitely for a zero
113308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * value.
113408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
113508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param timeout the read timeout value
113608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws SocketException if an error occurs setting the option
113708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
11390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setSoTimeout(int timeout) throws SocketException {
114008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super.setSoTimeout(timeout);
114108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.timeout = timeout;
114208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
114308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1144331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // BEGIN android-added
1145331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    /**
1146331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
1147331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * milliseconds and will be used only during the handshake process.
1148331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     *
1149331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * @param timeout the handshake timeout value
1150331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     */
11510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHandshakeTimeout(int timeout) throws SocketException {
1152331900211d05cd282141a3a50cb1db626f418b2cDan Egnor        this.handshakeTimeout = timeout;
1153331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    }
1154331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // END android-added
1155331900211d05cd282141a3a50cb1db626f418b2cDan Egnor
115608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
115708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Closes the SSL socket. Once closed, a socket is not available for further
115808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * use anymore under any circumstance. A new socket must be created.
115908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
116008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if an I/O error happens during the
116108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             socket's closure.
116208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11630b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
116408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void close() throws IOException {
116508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // TODO: Close SSL sockets using a background thread so they close
116608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // gracefully.
116708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
116808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        synchronized (handshakeLock) {
116908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (!handshakeStarted) {
11702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                // prevent further attemps to start handshake
117108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                handshakeStarted = true;
1172f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
117308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                synchronized (this) {
1174f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                    free();
117508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
117608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (socket != null) {
117708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (autoClose && !socket.isClosed()) socket.close();
117808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } else {
117908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (!super.isClosed()) super.close();
118008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
118108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                }
1182f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
118308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
118408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
118508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
118608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
118758a44774b954fed596ee22307a231de783ea8121Brian Carlstrom        NativeCrypto.SSL_interrupt(sslNativePointer);
118808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
118908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        synchronized (this) {
119008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            synchronized (writeLock) {
119108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                synchronized (readLock) {
119208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
119308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    IOException pendingException = null;
119408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
119508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    // Shut down the SSL connection, per se.
119608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    try {
119708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (handshakeStarted) {
1198ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick                            BlockGuard.getThreadPolicy().onNetwork();
119958a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                            NativeCrypto.SSL_shutdown(sslNativePointer);
120008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        }
120108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } catch (IOException ex) {
120208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        /*
120308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         * Note the exception at this point, but try to continue
120408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         * to clean the rest of this all up before rethrowing.
120508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         */
120608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        pendingException = ex;
120708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
120808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
120908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    /*
121008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * Even if the above call failed, it is still safe to free
121108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * the native structs, and we need to do so lest we leak
121208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * memory.
121308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     */
1214f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                    free();
121508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
121608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (socket != null) {
121708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (autoClose && !socket.isClosed())
121808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                            socket.close();
121908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } else {
122008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (!super.isClosed())
122108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                            super.close();
122208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
122308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
122408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (pendingException != null) {
122508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        throw pendingException;
122608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
122708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                }
122808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
122908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
123008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
123108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1232f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private void free() {
1233f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (sslNativePointer == 0) {
1234f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            return;
1235f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
1236f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1237f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        sslNativePointer = 0;
1238f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
123908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
12400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
124108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected void finalize() throws IOException {
124208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /*
12432828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * Just worry about our own state. Notably we do not try and
12442828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * close anything. The SocketImpl, either our own
12452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * PlainSocketImpl, or the Socket we are wrapping, will do
12462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * that. This might mean we do not properly SSL_shutdown, but
12472828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * if you want to do that, properly close the socket yourself.
12482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         *
12492828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * The reason why we don't try to SSL_shutdown, is that there
12502828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * can be a race between finalizers where the PlainSocketImpl
12512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * finalizer runs first and closes the socket. However, in the
12522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * meanwhile, the underlying file descriptor could be reused
12532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * for another purpose. If we call SSL_shutdown, the
12542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * underlying socket BIOs still have the old file descriptor
12552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * and will write the close notify to some unsuspecting
12562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * reader.
125708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
12582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        updateInstanceCount(-1);
12592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        free();
126008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
126108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project}
1262