OpenSSLSocketImpl.java revision ed2760e0dea39695b164af6d07ea9860e7c1fa49
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();
6508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private SSLParameters 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     */
10908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(SSLParameters 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     */
1212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    protected OpenSSLSocketImpl(SSLParameters 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     */
135c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom    protected OpenSSLSocketImpl(String host, int port, SSLParameters 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     */
147c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParameters 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,
162c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                SSLParameters 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,
176c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                SSLParameters 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,
18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            boolean autoClose, SSLParameters 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     */
203f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private void init(SSLParameters 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     */
2142828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private void init(SSLParameters 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            }
4652828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            byte[][] localCertificatesBytes = NativeCrypto.SSL_get_certificate(sslNativePointer);
4662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            X509Certificate[] localCertificates;
4672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (localCertificatesBytes == null) {
4682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                localCertificates = null;
46908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            } else {
4702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                localCertificates = new X509Certificate[localCertificatesBytes.length];
4712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                for (int i = 0; i < localCertificatesBytes.length; i++) {
47298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom                    localCertificates[i] = new X509CertImpl(localCertificatesBytes[i]);
4732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                }
474f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            }
47508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4766e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom            if (wrappedHost == null) {
4772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates,
478f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    super.getInetAddress().getHostName(),
479f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    super.getPort(), sessionContext);
480f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            } else  {
4812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates,
4826e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom                                                    wrappedHost, wrappedPort,
483f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                                                    sessionContext);
484f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            }
485c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom            // if not, putSession later in handshakeCompleted() callback
4862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (handshakeCompleted) {
487f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                sessionContext.putSession(sslSession);
488331900211d05cd282141a3a50cb1db626f418b2cDan Egnor            }
4892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            LoggerHolder.logger.fine("Created new session for "
4902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                                     + getInetAddress().getHostName() + ".");
49108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
49208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
493f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // BEGIN android-added
494f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // Restore the original timeout now that the handshake is complete
495f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (handshakeTimeout >= 0) {
496f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            setSoTimeout(savedTimeout);
497f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
498f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        // END android-added
499f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
500c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom        // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
5012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (handshakeCompleted) {
5022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            notifyHandshakeCompletedListeners();
50308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
50408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
50608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
507f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom    private void setCertificate(String alias) throws CertificateEncodingException, SSLException {
50898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        if (alias == null) {
50998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            return;
51098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
51198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
51298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias);
5131f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom        byte[] privateKeyBytes = privateKey.getEncoded();
51498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
51598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
51698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias);
517f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
51898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
51998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
52098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // checks the last installed private key and certificate,
52198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // so need to do this once per loop iteration
52298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        NativeCrypto.SSL_check_private_key(sslNativePointer);
52398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
52498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
52598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    /**
52698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
52798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * invoked via JNI from client_cert_cb
52898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     */
52998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
530f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            throws CertificateEncodingException, SSLException {
53198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom
53298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        String[] keyTypes = new String[keyTypeBytes.length];
53398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        for (int i = 0; i < keyTypeBytes.length; i++) {
53498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
53598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        }
53698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom
53798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        X500Principal[] issuers;
53898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        if (asn1DerEncodedPrincipals == null) {
53998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            issuers = null;
54098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        } else {
54198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            issuers = new X500Principal[asn1DerEncodedPrincipals.length];
54298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) {
54398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom                issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]);
54498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom            }
54598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        }
54698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom        setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this));
54798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
54898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
54908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
55098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
5512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * invoked via JNI from info_callback
55208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
5532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    public void handshakeCompleted() {
5542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        handshakeCompleted = true;
55508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // If sslSession is null, the handshake was completed during
5572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // the call to NativeCrypto.SSL_do_handshake and not during a
5582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // later read operation. That means we do not need to fixup
5592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // the SSLSession and session cache or notify
5602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // HandshakeCompletedListeners, it will be done in
5612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // startHandshake.
5622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (sslSession == null) {
5632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            return;
5642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
56508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // reset session id from the native pointer and update the
5672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // appropriate cache.
5682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        sslSession.resetId();
5692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        AbstractSessionContext sessionContext =
5702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            (sslParameters.getUseClientMode())
5712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            ? sslParameters.getClientSessionContext()
5722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                : sslParameters.getServerSessionContext();
57308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sessionContext.putSession(sslSession);
5742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // let listeners know we are finally done
5762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        notifyHandshakeCompletedListeners();
5772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
5782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
5802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
5812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // notify the listeners
5822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            HandshakeCompletedEvent event =
5832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
5842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
5852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                try {
5862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                    listener.handshakeCompleted(event);
5872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                } catch (RuntimeException e) {
588371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // The RI runs the handlers in a separate thread,
589371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // which we do not. But we try to preserve their
590371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // behavior of logging a problem and not killing
591371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // the handshaking thread just because a listener
592371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // has a problem.
593371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    Thread thread = Thread.currentThread();
594371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
5952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                }
5962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
5972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
59808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
59908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
60008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
60198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
602f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
60398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom     * @param bytes An array of ASN.1 DER encoded certficates
6042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @param authMethod auth algorithm name
60508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
6062828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * @throws CertificateException if the certificate is untrusted
60708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
60808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @SuppressWarnings("unused")
60998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    public void verifyCertificateChain(byte[][] bytes, String authMethod)
61098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            throws CertificateException {
61108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
612371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            if (bytes == null || bytes.length == 0) {
613371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                throw new SSLException("Peer sent no certificate");
614371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            }
6152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
6162828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (int i = 0; i < bytes.length; i++) {
61708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                peerCertificateChain[i] =
61898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                    new X509CertImpl(
61998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                        javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
62008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
6212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
6222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (client) {
62398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain,
62498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                                                                   authMethod);
6252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            } else {
62698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain,
62798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom                                                                   authMethod);
62808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
6292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
6302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (CertificateException e) {
6312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw e;
6322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (Exception e) {
6332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw new RuntimeException(e);
63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
63708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
63808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns an input stream for this SSL socket using native calls to the
63908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * OpenSSL library.
64008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return: an input stream for reading bytes from this socket.
64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws: <code>IOException</code> if an I/O error occurs when creating
64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *          the input stream, the socket is closed, the socket is not
64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *          connected, or the socket input has been shutdown.
64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
6460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public InputStream getInputStream() throws IOException {
648a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
649f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        synchronized (this) {
65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (is == null) {
65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                is = new SSLInputStream();
65208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return is;
65508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
65608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
65908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns an output stream for this SSL socket using native calls to the
66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * OpenSSL library.
66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
66208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an output stream for writing bytes to this socket.
66308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if an I/O error occurs when creating
66408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             the output stream, or no connection to the socket exists.
66508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
6660b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
66708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public OutputStream getOutputStream() throws IOException {
668a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
669f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom        synchronized (this) {
67008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (os == null) {
67108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                os = new SSLOutputStream();
67208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
67308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
67408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return os;
67508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
6792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * This method is not supported for this SSLSocket implementation
6802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * because reading from an SSLSocket may involve writing to the
6812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * network.
6822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
6830b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
68408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void shutdownInput() throws IOException {
6852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        throw new UnsupportedOperationException();
68608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
68708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
6892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * This method is not supported for this SSLSocket implementation
6902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * because writing to an SSLSocket may involve reading from the
6912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     * network.
6922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
6930b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void shutdownOutput() throws IOException {
6952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        throw new UnsupportedOperationException();
69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides input data stream functionality
70008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
70108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * read data received via SSL protocol.
70208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
70308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLInputStream extends InputStream {
70408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        SSLInputStream() throws IOException {
70508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /**
70608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /* Note: When startHandshake() throws an exception, no
70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             * SSLInputStream object will be created.
70808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             */
7092828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
71108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
71308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * this operation can block until the data will be
71508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * available.
71608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @return read value.
71708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @throws <code>IOException</code>
71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read() throws IOException {
721a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
722ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
723f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
72458a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                return NativeCrypto.SSL_read_byte(sslNativePointer, timeout);
72508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
72608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
72708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
72808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
72908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
73008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
73108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
73308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read(byte[] b, int off, int len) throws IOException {
734a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
735ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
736f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (b == null) {
737f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new NullPointerException("b == null");
738f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
739f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if ((len | off) < 0 || len > b.length - off) {
740f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new IndexOutOfBoundsException();
741f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
742f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (0 == len) {
743f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                return 0;
744f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
745f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
74658a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                return NativeCrypto.SSL_read(sslNativePointer, b, off, len, timeout);
74708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
74808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
74908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
75008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
75108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
75208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides output data stream functionality
75308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
75408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * write data according to the encryption parameters given in SSL context.
75508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLOutputStream extends OutputStream {
75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        SSLOutputStream() throws IOException {
75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /**
75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            /* Note: When startHandshake() throws an exception, no
760f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom             * SSLOutputStream object will be created.
76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project             */
7622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
76308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
76408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
76608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(int)
76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public void write(int b) throws IOException {
771a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
772ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
773f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
77458a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                NativeCrypto.SSL_write_byte(sslNativePointer, b);
77508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
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(byte[],int,int)
78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
78308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public void write(byte[] b, int start, int len) throws IOException {
784a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            checkOpen();
785ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
786f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (b == null) {
787f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new NullPointerException("b == null");
788f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
789f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if ((len | start) < 0 || len > b.length - start) {
790f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                throw new IndexOutOfBoundsException();
791f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
792f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            if (len == 0) {
793f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom                return;
794f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            }
795f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
79658a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                NativeCrypto.SSL_write(sslNativePointer, b, start, len);
79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
79908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
80008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
80108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
80308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The SSL session used by this connection is returned. The SSL session
80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * determines which cipher suite should be used by all connections within
80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * that session and which identities have the session's client and server.
80608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method starts the SSL handshake.
80708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return the SSLSession.
80808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if the handshake fails
80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
81108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public SSLSession getSession() {
81208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
8132828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            startHandshake(true);
81408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (IOException e) {
81508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // return an invalid session with
81608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
81708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return SSLSessionImpl.NULL_SESSION;
81808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
81908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslSession;
82008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
82108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
82208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
82308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Registers a listener to be notified that a SSL handshake
82408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * was successfully completed on this connection.
82508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IllegalArgumentException</code> if listener is null.
82608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
82808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void addHandshakeCompletedListener(
82908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
83008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
83108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
83208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
83308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
83408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            listeners = new ArrayList();
83508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
83608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        listeners.add(listener);
83708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
83808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
83908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The method removes a registered listener.
84108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException if listener is null or not registered
84208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
84408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void removeHandshakeCompletedListener(
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            throw new IllegalArgumentException(
85108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
85208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
85308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!listeners.remove(listener)) {
85408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
85508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
85608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
85708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
85808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
85908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
86008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if new SSL sessions may be established by this socket.
86108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
86208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if the session may be created; false if a session already
86308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *         exists and must be resumed.
86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getEnableSessionCreation() {
86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getEnableSessionCreation();
86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
86908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
87008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Set a flag for the socket to inhibit or to allow the creation of a new
87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * SSL sessions. If the flag is set to false, and there are no actual
87308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * sessions to resume, then there will be no successful handshaking.
87408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
87508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param flag true if session may be created; false
87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            if a session already exists and must be resumed.
87708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
88108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
88208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
88308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
88408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the cipher suites which could be used by the SSL connection
88508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * are returned.
88608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of cipher suite names
88708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getSupportedCipherSuites() {
890f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
89108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
89208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
89308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
89408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the cipher suites that are in use in the actual the SSL
89508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection are returned.
89608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
89708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of cipher suite names
89808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
8990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
90008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getEnabledCipherSuites() {
9012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        return enabledCipherSuites.clone();
90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
90308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
90408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
90508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method enables the cipher suites listed by
90608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * getSupportedCipherSuites().
90708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
90808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param suites names of all the cipher suites to
90908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            put on use
91008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException when one or more of the
91108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             ciphers in array suites are not supported, or when the array
91208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             is null.
91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
91508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
9162828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites);
91708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
92008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the protocols' versions that may be used on this SSL
92108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection.
92208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of protocols names
92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
9240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
92508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getSupportedProtocols() {
926f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
92808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
92908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
93008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * The names of the protocols' versions that are in use on this SSL
93108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * connection.
932f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
93308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return an array of protocols names
93408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
93508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @Override
93608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public String[] getEnabledProtocols() {
9372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        return enabledProtocols.clone();
93808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
93908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
94008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
94108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method enables the protocols' versions listed by
94208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * getSupportedProtocols().
943f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
9440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param protocols The names of all the protocols to allow
945f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom     *
94608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException when one or more of the names in the
94708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             array are not supported, or when the array is null.
94808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
94908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    @Override
9500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setEnabledProtocols(String[] protocols) {
9512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols);
95208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
95308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
95408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
9550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * The names of the compression methods that may be used on this SSL
9560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * connection.
9570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return an array of compression methods
9580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String[] getSupportedCompressionMethods() {
9600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return NativeCrypto.getSupportedCompressionMethods();
9610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9620b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9630b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9640b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * The names of the compression methods versions that are in use
9650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * on this SSL connection.
9660b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9670b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return an array of compression methods
9680b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String[] getEnabledCompressionMethods() {
9700b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return enabledCompressionMethods.clone();
9710b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9720b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9740b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables the compression method listed by
9750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * getSupportedCompressionMethods().
9760b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param methods The names of all the compression methods to allow
9780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9790b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @throws IllegalArgumentException when one or more of the names in the
9800b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *             array are not supported, or when the array is null.
9810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setEnabledCompressionMethods (String[] methods) {
9830b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods);
9840b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9850b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9860b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9870b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables session ticket support.
9880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9890b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param useSessionTickets True to enable session tickets
9900b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9910b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
9920b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        this.useSessionTickets = useSessionTickets;
9930b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9940b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9950b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9960b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method gives true back if the SSL socket is set to client mode.
9970b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9980b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return true if the socket should do the handshaking as client.
9990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10000b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public boolean getUseSessionTickets() {
10010b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return useSessionTickets;
10020b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10040b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10050b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables Server Name Indication
10060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
10080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10090b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHostname(String hostname) {
10100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        this.hostname = hostname;
10110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
10140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method returns the current SNI hostname
10150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
10160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @return a host name if SNI is enabled, or null otherwise
10170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
10180b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public String getHostname() {
10190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        return hostname;
10200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
10210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
10220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
102308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method gives true back if the SSL socket is set to client mode.
102408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
102508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if the socket should do the handshaking as client.
102608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
102708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getUseClientMode() {
102808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getUseClientMode();
102908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
103008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
103108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
103208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method set the actual SSL socket to client mode.
103308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
103408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param mode true if the socket starts in client
103508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            mode
103608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws IllegalArgumentException if mode changes during
103708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             handshake.
103808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
10400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseClientMode(boolean mode) {
104108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (handshakeStarted) {
104208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
104308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
104408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
104508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setUseClientMode(mode);
104608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
104708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
104808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
104908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if the SSL socket requests client's authentication. Relevant
105008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * only for server sockets!
105108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
105208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if client authentication is desired, false if not.
105308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
105508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getWantClientAuth() {
105608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getWantClientAuth();
105708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
105808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
105908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
106008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Returns true if the SSL socket needs client's authentication. Relevant
106108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * only for server sockets!
106208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
106308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return true if client authentication is desired, false if not.
106408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
106608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public boolean getNeedClientAuth() {
106708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getNeedClientAuth();
106808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
106908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
107008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
107108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
107208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * server sockets!
107308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
107408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param need true if client authentication is
107508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            desired, false if not.
107608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
107808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setNeedClientAuth(boolean need) {
107908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setNeedClientAuth(need);
108008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
108108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
108208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
108308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
108408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * server sockets! Notice that in contrast to setNeedClientAuth(..) this
108508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * method will continue the negotiation if the client decide not to send
108608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * authentication credentials.
108708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
108808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param want true if client authentication is
108908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *            desired, false if not.
109008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10910b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
109208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setWantClientAuth(boolean want) {
109308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setWantClientAuth(want);
109408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
109508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
109608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
109708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method is not supported for SSLSocket implementation.
109808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
10990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
110008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void sendUrgentData(int data) throws IOException {
110108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throw new SocketException(
110208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                "Method sendUrgentData() is not supported.");
110308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
110408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
110508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
110608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This method is not supported for SSLSocket implementation.
110708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
110908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void setOOBInline(boolean on) throws SocketException {
111008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        throw new SocketException(
111108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                "Methods sendUrgentData, setOOBInline are not supported.");
111208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
111308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
111408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
111508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
111608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * in milliseconds. The read operation will block indefinitely for a zero
111708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * value.
111808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
111908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param timeout the read timeout value
112008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws SocketException if an error occurs setting the option
112108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
11230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setSoTimeout(int timeout) throws SocketException {
112408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super.setSoTimeout(timeout);
112508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.timeout = timeout;
112608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
112708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1128331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // BEGIN android-added
1129331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    /**
1130331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
1131331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * milliseconds and will be used only during the handshake process.
1132331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     *
1133331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * @param timeout the handshake timeout value
1134331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     */
11350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHandshakeTimeout(int timeout) throws SocketException {
1136331900211d05cd282141a3a50cb1db626f418b2cDan Egnor        this.handshakeTimeout = timeout;
1137331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    }
1138331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    // END android-added
1139331900211d05cd282141a3a50cb1db626f418b2cDan Egnor
114008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
114108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Closes the SSL socket. Once closed, a socket is not available for further
114208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * use anymore under any circumstance. A new socket must be created.
114308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
114408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @throws <code>IOException</code> if an I/O error happens during the
114508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *             socket's closure.
114608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
11470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
114808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public void close() throws IOException {
114908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // TODO: Close SSL sockets using a background thread so they close
115008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // gracefully.
115108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
115208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        synchronized (handshakeLock) {
115308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (!handshakeStarted) {
11542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                // prevent further attemps to start handshake
115508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                handshakeStarted = true;
1156f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
115708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                synchronized (this) {
1158f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                    free();
115908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
116008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (socket != null) {
116108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (autoClose && !socket.isClosed()) socket.close();
116208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } else {
116308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (!super.isClosed()) super.close();
116408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
116508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                }
1166f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
116708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
116808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
116908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
117008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
117158a44774b954fed596ee22307a231de783ea8121Brian Carlstrom        NativeCrypto.SSL_interrupt(sslNativePointer);
117208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
117308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        synchronized (this) {
117408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            synchronized (writeLock) {
117508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                synchronized (readLock) {
117608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
117708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    IOException pendingException = null;
117808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
117908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    // Shut down the SSL connection, per se.
118008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    try {
118108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (handshakeStarted) {
1182ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick                            BlockGuard.getThreadPolicy().onNetwork();
118358a44774b954fed596ee22307a231de783ea8121Brian Carlstrom                            NativeCrypto.SSL_shutdown(sslNativePointer);
118408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        }
118508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } catch (IOException ex) {
118608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        /*
118708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         * Note the exception at this point, but try to continue
118808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         * to clean the rest of this all up before rethrowing.
118908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                         */
119008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        pendingException = ex;
119108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
119208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
119308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    /*
119408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * Even if the above call failed, it is still safe to free
119508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * the native structs, and we need to do so lest we leak
119608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     * memory.
119708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                     */
1198f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom                    free();
119908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
120008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (socket != null) {
120108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (autoClose && !socket.isClosed())
120208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                            socket.close();
120308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    } else {
120408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        if (!super.isClosed())
120508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                            super.close();
120608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
120708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
120808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    if (pendingException != null) {
120908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                        throw pendingException;
121008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    }
121108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                }
121208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
121308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
121408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
121508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1216f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private void free() {
1217f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (sslNativePointer == 0) {
1218f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            return;
1219f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
1220f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1221f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        sslNativePointer = 0;
1222f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
122308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
12240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    @Override
122508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected void finalize() throws IOException {
122608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /*
12272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * Just worry about our own state. Notably we do not try and
12282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * close anything. The SocketImpl, either our own
12292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * PlainSocketImpl, or the Socket we are wrapping, will do
12302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * that. This might mean we do not properly SSL_shutdown, but
12312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * if you want to do that, properly close the socket yourself.
12322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         *
12332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * The reason why we don't try to SSL_shutdown, is that there
12342828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * can be a race between finalizers where the PlainSocketImpl
12352828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * finalizer runs first and closes the socket. However, in the
12362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * meanwhile, the underlying file descriptor could be reused
12372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * for another purpose. If we call SSL_shutdown, the
12382828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * underlying socket BIOs still have the old file descriptor
12392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * and will write the close notify to some unsuspecting
12402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom         * reader.
124108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
12422828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        updateInstanceCount(-1);
12432828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        free();
124408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
124508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project}
1246