1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.BufferUnderflowException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ReadOnlyBufferException;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLEngine;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLEngineResult;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException;
280c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport javax.net.ssl.SSLHandshakeException;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implementation of SSLEngine.
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see javax.net.ssl.SSLEngine class documentation for more information.
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class SSLEngineImpl extends SSLEngine {
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if peer mode was set
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean peer_mode_was_set = false;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if handshake has been started
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean handshake_started = false;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if inbound operations finished
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isInboundDone = false;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if outbound operations finished
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isOutboundDone = false;
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if close_notify alert had been sent to another peer
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean close_notify_was_sent = false;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if close_notify alert had been received from another peer
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean close_notify_was_received = false;
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if engine was closed (it means that
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // all the works on it are done, except (probably) some finalizing work)
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean engine_was_closed = false;
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // indicates if engine was shutted down (it means that
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // all cleaning work had been done and the engine is not operable)
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean engine_was_shutteddown = false;
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // record protocol to be used
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected SSLRecordProtocol recordProtocol;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // input stream for record protocol
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLBufferedInput recProtIS;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // handshake protocol to be used
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private HandshakeProtocol handshakeProtocol;
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // alert protocol to be used
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private AlertProtocol alertProtocol;
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // place where application data will be stored
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLEngineAppData appData;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // outcoming application data stream
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLEngineDataStream dataStream = new SSLEngineDataStream();
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // active session object
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLSessionImpl session;
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // peer configuration parameters
726812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLParametersImpl sslParameters;
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // in case of emergency situations when data could not be
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // placed in destination buffers it will be stored in this
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // fields
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] remaining_wrapped_data = null;
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] remaining_hsh_data = null;
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // logger
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Logger.Stream logger = Logger.getStream("engine");
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
836812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLEngineImpl(SSLParametersImpl sslParameters) {
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.sslParameters = sslParameters;
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
876812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) {
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port);
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.sslParameters = sslParameters;
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts the handshake.
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws  SSLException
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#beginHandshake() method documentation
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for more information
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
98f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void beginHandshake() throws SSLException {
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (engine_was_closed) {
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new SSLException("Engine has already been closed.");
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!peer_mode_was_set) {
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalStateException("Client/Server mode was not set");
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!handshake_started) {
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            handshake_started = true;
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (getUseClientMode()) {
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeProtocol = new ClientHandshakeImpl(this);
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeProtocol = new ServerHandshakeImpl(this);
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            appData = new SSLEngineAppData();
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol = new AlertProtocol();
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recProtIS = new SSLBufferedInput();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recordProtocol = new SSLRecordProtocol(handshakeProtocol,
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    alertProtocol, recProtIS, appData);
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        handshakeProtocol.start();
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes inbound operations of this engine
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws  SSLException
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#closeInbound() method documentation
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for more information
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
128f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void closeInbound() throws SSLException {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (logger != null) {
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            logger.println("closeInbound() "+isInboundDone);
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isInboundDone) {
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isInboundDone = true;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        engine_was_closed = true;
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshake_started) {
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!close_notify_was_received) {
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (session != null) {
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.invalidate();
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                alertProtocol.alert(AlertProtocol.FATAL,
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        AlertProtocol.INTERNAL_ERROR);
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new SSLException("Inbound is closed before close_notify "
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + "alert has been received.");
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // engine is closing before initial handshake has been made
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            shutdown();
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes outbound operations of this engine
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#closeOutbound() method documentation
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for more information
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
159f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void closeOutbound() {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (logger != null) {
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            logger.println("closeOutbound() "+isOutboundDone);
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isOutboundDone) {
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isOutboundDone = true;
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshake_started) {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // initial handshake had been started
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol.alert(AlertProtocol.WARNING,
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    AlertProtocol.CLOSE_NOTIFY);
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            close_notify_was_sent = true;
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // engine is closing before initial handshake has been made
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            shutdown();
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        engine_was_closed = true;
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns handshake's delegated tasks to be run
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the delegated task to be executed.
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getDelegatedTask() method documentation
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for more information
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
186f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Runnable getDelegatedTask() {
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return handshakeProtocol.getTask();
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns names of supported cipher suites.
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return array of strings containing the names of supported cipher suites
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getSupportedCipherSuites() method
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
197f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedCipherSuites() {
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return CipherSuite.getSupportedCipherSuiteNames();
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // --------------- SSLParameters based methods ---------------------
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getEnabledCipherSuites() method
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
209f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledCipherSuites() {
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnabledCipherSuites();
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setEnabledCipherSuites(String[]) method
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
219f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnabledCipherSuites(suites);
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getSupportedProtocols() method
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
229f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedProtocols() {
231f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        return ProtocolVersion.supportedProtocols.clone();
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getEnabledProtocols() method
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
239f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledProtocols() {
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnabledProtocols();
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setEnabledProtocols(String[]) method
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
249f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnabledProtocols(String[] protocols) {
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnabledProtocols(protocols);
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setUseClientMode(boolean) method
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
259f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setUseClientMode(boolean mode) {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshake_started) {
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setUseClientMode(mode);
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        peer_mode_was_set = true;
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getUseClientMode() method
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
274f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getUseClientMode() {
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getUseClientMode();
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setNeedClientAuth(boolean) method
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
284f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setNeedClientAuth(boolean need) {
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setNeedClientAuth(need);
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getNeedClientAuth() method
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
294f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getNeedClientAuth() {
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getNeedClientAuth();
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setWantClientAuth(boolean) method
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
304f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setWantClientAuth(boolean want) {
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setWantClientAuth(want);
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getWantClientAuth() method
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
314f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getWantClientAuth() {
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getWantClientAuth();
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#setEnableSessionCreation(boolean) method
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
324f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getEnableSessionCreation() method
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
334f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getEnableSessionCreation() {
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnableSessionCreation();
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // -----------------------------------------------------------------
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getHandshakeStatus() method
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
346f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!handshake_started || engine_was_shutteddown) {
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // initial handshake has not been started yet
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (alertProtocol.hasAlert()) {
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // need to send an alert
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return SSLEngineResult.HandshakeStatus.NEED_WRAP;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (close_notify_was_sent && !close_notify_was_received) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // waiting for "close_notify" response
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return handshakeProtocol.getStatus();
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#getSession() method
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
368f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLSession getSession() {
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session != null) {
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return session;
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
373f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        return SSLSessionImpl.NULL_SESSION;
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#isInboundDone() method
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
381f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isInboundDone() {
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isInboundDone || engine_was_closed;
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method works according to the specification of implemented class.
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#isOutboundDone() method
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
391f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isOutboundDone() {
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return isOutboundDone;
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Decodes one complete SSL/TLS record provided in the source buffer.
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If decoded record contained application data, this data will
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * be placed in the destination buffers.
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * For more information about TLS record fragmentation see
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param src source buffer containing SSL/TLS record.
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dsts destination buffers to place received application data.
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#unwrap(ByteBuffer,ByteBuffer[],int,int)
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method documentation for more information
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
407f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts,
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                int offset, int length) throws SSLException {
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (engine_was_shutteddown) {
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((src == null) || (dsts == null)) {
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalStateException(
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Some of the input parameters are null");
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!handshake_started) {
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            beginHandshake();
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If is is initial handshake or connection closure stage,
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check if this call was made in spite of handshake status
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((session == null || engine_was_closed) && (
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    handshakeStatus.equals(
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NEED_WRAP) ||
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    handshakeStatus.equals(
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NEED_TASK))) {
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    getEngineStatus(), handshakeStatus, 0, 0);
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (src.remaining() < recordProtocol.getMinRecordSize()) {
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    SSLEngineResult.Status.BUFFER_UNDERFLOW,
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    getHandshakeStatus(), 0, 0);
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            src.mark();
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // check the destination buffers and count their capacity
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int capacity = 0;
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i=offset; i<offset+length; i++) {
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (dsts[i] == null) {
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalStateException(
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            "Some of the input parameters are null");
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (dsts[i].isReadOnly()) {
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new ReadOnlyBufferException();
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                capacity += dsts[i].remaining();
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (capacity < recordProtocol.getDataSize(src.remaining())) {
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SSLEngineResult(
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.Status.BUFFER_OVERFLOW,
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        getHandshakeStatus(), 0, 0);
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recProtIS.setSourceBuffer(src);
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // unwrap the record contained in source buffer, pass it
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // to appropriate client protocol (alert, handshake, or app)
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // and retrieve the type of unwrapped data
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int type = recordProtocol.unwrap();
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // process the data and return the result
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (type) {
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case ContentType.HANDSHAKE:
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case ContentType.CHANGE_CIPHER_SPEC:
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (handshakeProtocol.getStatus().equals(
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.HandshakeStatus.FINISHED)) {
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session = recordProtocol.getSession();
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case ContentType.APPLICATION_DATA:
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case ContentType.ALERT:
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (alertProtocol.isFatalAlert()) {
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        alertProtocol.setProcessed();
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (session != null) {
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            session.invalidate();
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        String description = "Fatal alert received "
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            + alertProtocol.getAlertDescription();
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        shutdown();
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        throw new SSLException(description);
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (logger != null) {
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            logger.println("Warning allert has been received: "
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + alertProtocol.getAlertDescription());
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        switch(alertProtocol.getDescriptionCode()) {
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            case AlertProtocol.CLOSE_NOTIFY:
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                alertProtocol.setProcessed();
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                close_notify_was_received = true;
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                if (!close_notify_was_sent) {
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    closeOutbound();
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    closeInbound();
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                } else {
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    closeInbound();
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    shutdown();
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                }
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                break;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            case AlertProtocol.NO_RENEGOTIATION:
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                alertProtocol.setProcessed();
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                if (session == null) {
506f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                                    // message received during the initial
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    // handshake
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    throw new AlertException(
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        AlertProtocol.HANDSHAKE_FAILURE,
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        new SSLHandshakeException(
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                            "Received no_renegotiation "
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                            + "during the initial handshake"));
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                } else {
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    // just stop the handshake
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    handshakeProtocol.stop();
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                }
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                break;
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            default:
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                alertProtocol.setProcessed();
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(),
525f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    recProtIS.consumed(),
526f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    // place the app. data (if any) into the dest. buffers
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // and get the number of produced bytes:
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    appData.placeTo(dsts, offset, length));
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (BufferUnderflowException e) {
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // there was not enought data ource buffer to make complete packet
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            src.reset();
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW,
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    getHandshakeStatus(), 0, 0);
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (AlertException e) {
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // fatal alert occured
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol.alert(AlertProtocol.FATAL, e.getDescriptionCode());
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engine_was_closed = true;
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            src.reset();
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (session != null) {
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session.invalidate();
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // shutdown work will be made after the alert will be sent
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // to another peer (by wrap method)
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw e.getReason();
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (SSLException e) {
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw e;
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IOException e) {
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol.alert(AlertProtocol.FATAL,
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    AlertProtocol.INTERNAL_ERROR);
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engine_was_closed = true;
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // shutdown work will be made after the alert will be sent
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // to another peer (by wrap method)
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new SSLException(e.getMessage());
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Encodes the application data into SSL/TLS record. If handshake status
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the engine differs from NOT_HANDSHAKING the operation can work
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * without consuming of the source data.
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * For more information about TLS record fragmentation see
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param srcs the source buffers with application data to be encoded
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * into SSL/TLS record.
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset the offset in the destination buffers array pointing to
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the first buffer with the source data.
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param len specifies the maximum number of buffers to be procesed.
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dst the destination buffer where encoded data will be placed.
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see javax.net.ssl.SSLEngine#wrap(ByteBuffer[],int,int,ByteBuffer) method
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * documentation for more information
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
572f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLEngineResult wrap(ByteBuffer[] srcs, int offset,
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            int len, ByteBuffer dst) throws SSLException {
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (engine_was_shutteddown) {
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((srcs == null) || (dst == null)) {
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalStateException(
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Some of the input parameters are null");
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dst.isReadOnly()) {
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new ReadOnlyBufferException();
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!handshake_started) {
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            beginHandshake();
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If it is an initial handshake or connection closure stage,
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check if this call was made in spite of handshake status
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((session == null || engine_was_closed) && (
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStatus.equals(
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NEED_UNWRAP) ||
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStatus.equals(
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NEED_TASK))) {
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    getEngineStatus(), handshakeStatus, 0, 0);
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int capacity = dst.remaining();
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int produced = 0;
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (alertProtocol.hasAlert()) {
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // we have an alert to be sent
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (capacity < recordProtocol.getRecordSize(2)) {
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SSLEngineResult(
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.Status.BUFFER_OVERFLOW,
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        handshakeStatus, 0, 0);
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] alert_data = alertProtocol.wrap();
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // place the alert record into destination
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dst.put(alert_data);
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (alertProtocol.isFatalAlert()) {
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                alertProtocol.setProcessed();
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (session != null) {
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.invalidate();
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // fatal alert has been sent, so shut down the engine
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                shutdown();
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SSLEngineResult(
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.Status.CLOSED,
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        0, alert_data.length);
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                alertProtocol.setProcessed();
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check if the works on this engine have been done
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (close_notify_was_sent && close_notify_was_received) {
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    shutdown();
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            0, alert_data.length);
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SSLEngineResult(
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        getEngineStatus(),
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        getHandshakeStatus(),
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        0, alert_data.length);
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (capacity < recordProtocol.getMinRecordSize()) {
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (logger != null) {
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                logger.println("Capacity of the destination("
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        +capacity+") < MIN_PACKET_SIZE("
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        +recordProtocol.getMinRecordSize()+")");
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW,
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        handshakeStatus, 0, 0);
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStatus.equals(
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // so we wraps application data
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                dataStream.setSourceBuffers(srcs, offset, len);
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if ((capacity < SSLRecordProtocol.MAX_SSL_PACKET_SIZE) &&
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    (capacity < recordProtocol.getRecordSize(
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                 dataStream.available()))) {
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (logger != null) {
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        logger.println("The destination buffer("
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                +capacity+") can not take the resulting packet("
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + recordProtocol.getRecordSize(
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    dataStream.available())+")");
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return new SSLEngineResult(
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.Status.BUFFER_OVERFLOW,
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            handshakeStatus, 0, 0);
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (remaining_wrapped_data == null) {
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    remaining_wrapped_data =
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        recordProtocol.wrap(ContentType.APPLICATION_DATA,
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                dataStream);
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (capacity < remaining_wrapped_data.length) {
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // It should newer happen because we checked the destination
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // buffer size, but there is a possibility
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // (if dest buffer was filled outside)
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // so we just remember the data into remaining_wrapped_data
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // and will enclose it during the the next call
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return new SSLEngineResult(
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.Status.BUFFER_OVERFLOW,
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            handshakeStatus, dataStream.consumed(), 0);
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dst.put(remaining_wrapped_data);
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    produced = remaining_wrapped_data.length;
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    remaining_wrapped_data = null;
689f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    return new SSLEngineResult(getEngineStatus(),
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            handshakeStatus, dataStream.consumed(), produced);
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (remaining_hsh_data == null) {
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    remaining_hsh_data = handshakeProtocol.wrap();
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (capacity < remaining_hsh_data.length) {
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // It should newer happen because we checked the destination
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // buffer size, but there is a possibility
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // (if dest buffer was filled outside)
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // so we just remember the data into remaining_hsh_data
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // and will enclose it during the the next call
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return new SSLEngineResult(
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.Status.BUFFER_OVERFLOW,
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            handshakeStatus, 0, 0);
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dst.put(remaining_hsh_data);
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    produced = remaining_hsh_data.length;
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    remaining_hsh_data = null;
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    handshakeStatus = handshakeProtocol.getStatus();
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (handshakeStatus.equals(
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            SSLEngineResult.HandshakeStatus.FINISHED)) {
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session = recordProtocol.getSession();
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return new SSLEngineResult(
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        getEngineStatus(), getHandshakeStatus(), 0, produced);
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (AlertException e) {
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // fatal alert occured
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol.alert(AlertProtocol.FATAL, e.getDescriptionCode());
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            engine_was_closed = true;
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (session != null) {
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session.invalidate();
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // shutdown work will be made after the alert will be sent
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // to another peer (by wrap method)
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw e.getReason();
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Shutdownes the engine and makes all cleanup work.
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void shutdown() {
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        engine_was_closed = true;
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        engine_was_shutteddown = true;
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isOutboundDone = true;
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isInboundDone = true;
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshake_started) {
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol.shutdown();
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            alertProtocol = null;
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            handshakeProtocol.shutdown();
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            handshakeProtocol = null;
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recordProtocol.shutdown();
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recordProtocol = null;
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLEngineResult.Status getEngineStatus() {
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (engine_was_closed)
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ? SSLEngineResult.Status.CLOSED
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            : SSLEngineResult.Status.OK;
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
755