
com.bugvm.conscrypt.SSLEngineImpl Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bugvm.conscrypt;
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
/**
* Implementation of SSLEngine.
* @see javax.net.ssl.SSLEngine class documentation for more information.
*/
public class SSLEngineImpl extends SSLEngine {
// indicates if peer mode was set
private boolean peer_mode_was_set = false;
// indicates if handshake has been started
private boolean handshake_started = false;
// indicates if inbound operations finished
private boolean isInboundDone = false;
// indicates if outbound operations finished
private boolean isOutboundDone = false;
// indicates if close_notify alert had been sent to another peer
private boolean close_notify_was_sent = false;
// indicates if close_notify alert had been received from another peer
private boolean close_notify_was_received = false;
// indicates if engine was closed (it means that
// all the works on it are done, except (probably) some finalizing work)
private boolean engine_was_closed = false;
// indicates if engine was shutted down (it means that
// all cleaning work had been done and the engine is not operable)
private boolean engine_was_shutteddown = false;
// record protocol to be used
protected SSLRecordProtocol recordProtocol;
// input stream for record protocol
private SSLBufferedInput recProtIS;
// handshake protocol to be used
private HandshakeProtocol handshakeProtocol;
// alert protocol to be used
private AlertProtocol alertProtocol;
// place where application data will be stored
private SSLEngineAppData appData;
// outcoming application data stream
private SSLEngineDataStream dataStream = new SSLEngineDataStream();
// active session object
private SSLSessionImpl session;
// peer configuration parameters
protected SSLParametersImpl sslParameters;
// in case of emergency situations when data could not be
// placed in destination buffers it will be stored in this
// fields
private byte[] remaining_wrapped_data = null;
private byte[] remaining_hsh_data = null;
// logger
private Logger.Stream logger = Logger.getStream("engine");
protected SSLEngineImpl(SSLParametersImpl sslParameters) {
this.sslParameters = sslParameters;
}
protected SSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) {
super(host, port);
this.sslParameters = sslParameters;
}
/**
* Starts the handshake.
* @throws SSLException
* @see javax.net.ssl.SSLEngine#beginHandshake() method documentation
* for more information
*/
@Override
public void beginHandshake() throws SSLException {
if (engine_was_closed) {
throw new SSLException("Engine has already been closed.");
}
if (!peer_mode_was_set) {
throw new IllegalStateException("Client/Server mode was not set");
}
if (!handshake_started) {
handshake_started = true;
if (getUseClientMode()) {
handshakeProtocol = new ClientHandshakeImpl(this);
} else {
handshakeProtocol = new ServerHandshakeImpl(this);
}
appData = new SSLEngineAppData();
alertProtocol = new AlertProtocol();
recProtIS = new SSLBufferedInput();
recordProtocol = new SSLRecordProtocol(handshakeProtocol,
alertProtocol, recProtIS, appData);
}
handshakeProtocol.start();
}
/**
* Closes inbound operations of this engine
* @throws SSLException
* @see javax.net.ssl.SSLEngine#closeInbound() method documentation
* for more information
*/
@Override
public void closeInbound() throws SSLException {
if (logger != null) {
logger.println("closeInbound() "+isInboundDone);
}
if (isInboundDone) {
return;
}
isInboundDone = true;
engine_was_closed = true;
if (handshake_started) {
if (!close_notify_was_received) {
if (session != null) {
session.invalidate();
}
alertProtocol.alert(AlertProtocol.FATAL,
AlertProtocol.INTERNAL_ERROR);
throw new SSLException("Inbound is closed before close_notify "
+ "alert has been received.");
}
} else {
// engine is closing before initial handshake has been made
shutdown();
}
}
/**
* Closes outbound operations of this engine
* @see javax.net.ssl.SSLEngine#closeOutbound() method documentation
* for more information
*/
@Override
public void closeOutbound() {
if (logger != null) {
logger.println("closeOutbound() "+isOutboundDone);
}
if (isOutboundDone) {
return;
}
isOutboundDone = true;
if (handshake_started) {
// initial handshake had been started
alertProtocol.alert(AlertProtocol.WARNING,
AlertProtocol.CLOSE_NOTIFY);
close_notify_was_sent = true;
} else {
// engine is closing before initial handshake has been made
shutdown();
}
engine_was_closed = true;
}
/**
* Returns handshake's delegated tasks to be run
* @return the delegated task to be executed.
* @see javax.net.ssl.SSLEngine#getDelegatedTask() method documentation
* for more information
*/
@Override
public Runnable getDelegatedTask() {
return handshakeProtocol.getTask();
}
/**
* Returns names of supported cipher suites.
* @return array of strings containing the names of supported cipher suites
* @see javax.net.ssl.SSLEngine#getSupportedCipherSuites() method
* documentation for more information
*/
@Override
public String[] getSupportedCipherSuites() {
return CipherSuite.getSupportedCipherSuiteNames();
}
// --------------- SSLParameters based methods ---------------------
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getEnabledCipherSuites() method
* documentation for more information
*/
@Override
public String[] getEnabledCipherSuites() {
return sslParameters.getEnabledCipherSuites();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setEnabledCipherSuites(String[]) method
* documentation for more information
*/
@Override
public void setEnabledCipherSuites(String[] suites) {
sslParameters.setEnabledCipherSuites(suites);
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getSupportedProtocols() method
* documentation for more information
*/
@Override
public String[] getSupportedProtocols() {
return ProtocolVersion.supportedProtocols.clone();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getEnabledProtocols() method
* documentation for more information
*/
@Override
public String[] getEnabledProtocols() {
return sslParameters.getEnabledProtocols();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setEnabledProtocols(String[]) method
* documentation for more information
*/
@Override
public void setEnabledProtocols(String[] protocols) {
sslParameters.setEnabledProtocols(protocols);
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setUseClientMode(boolean) method
* documentation for more information
*/
@Override
public void setUseClientMode(boolean mode) {
if (handshake_started) {
throw new IllegalArgumentException(
"Could not change the mode after the initial handshake has begun.");
}
sslParameters.setUseClientMode(mode);
peer_mode_was_set = true;
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getUseClientMode() method
* documentation for more information
*/
@Override
public boolean getUseClientMode() {
return sslParameters.getUseClientMode();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setNeedClientAuth(boolean) method
* documentation for more information
*/
@Override
public void setNeedClientAuth(boolean need) {
sslParameters.setNeedClientAuth(need);
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getNeedClientAuth() method
* documentation for more information
*/
@Override
public boolean getNeedClientAuth() {
return sslParameters.getNeedClientAuth();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setWantClientAuth(boolean) method
* documentation for more information
*/
@Override
public void setWantClientAuth(boolean want) {
sslParameters.setWantClientAuth(want);
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getWantClientAuth() method
* documentation for more information
*/
@Override
public boolean getWantClientAuth() {
return sslParameters.getWantClientAuth();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#setEnableSessionCreation(boolean) method
* documentation for more information
*/
@Override
public void setEnableSessionCreation(boolean flag) {
sslParameters.setEnableSessionCreation(flag);
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getEnableSessionCreation() method
* documentation for more information
*/
@Override
public boolean getEnableSessionCreation() {
return sslParameters.getEnableSessionCreation();
}
// -----------------------------------------------------------------
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getHandshakeStatus() method
* documentation for more information
*/
@Override
public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
if (!handshake_started || engine_was_shutteddown) {
// initial handshake has not been started yet
return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
if (alertProtocol.hasAlert()) {
// need to send an alert
return SSLEngineResult.HandshakeStatus.NEED_WRAP;
}
if (close_notify_was_sent && !close_notify_was_received) {
// waiting for "close_notify" response
return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
}
return handshakeProtocol.getStatus();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#getSession() method
* documentation for more information
*/
@Override
public SSLSession getSession() {
if (session != null) {
return session;
}
return SSLSessionImpl.getNullSession();
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#isInboundDone() method
* documentation for more information
*/
@Override
public boolean isInboundDone() {
return isInboundDone || engine_was_closed;
}
/**
* This method works according to the specification of implemented class.
* @see javax.net.ssl.SSLEngine#isOutboundDone() method
* documentation for more information
*/
@Override
public boolean isOutboundDone() {
return isOutboundDone;
}
/**
* Decodes one complete SSL/TLS record provided in the source buffer.
* If decoded record contained application data, this data will
* be placed in the destination buffers.
* For more information about TLS record fragmentation see
* TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
* @param src source buffer containing SSL/TLS record.
* @param dsts destination buffers to place received application data.
* @see javax.net.ssl.SSLEngine#unwrap(ByteBuffer,ByteBuffer[],int,int)
* method documentation for more information
*/
@Override
public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts,
int offset, int length) throws SSLException {
if (engine_was_shutteddown) {
return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
if ((src == null) || (dsts == null)) {
throw new IllegalStateException(
"Some of the input parameters are null");
}
if (!handshake_started) {
beginHandshake();
}
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
// If is is initial handshake or connection closure stage,
// check if this call was made in spite of handshake status
if ((session == null || engine_was_closed) && (
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_WRAP) ||
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_TASK))) {
return new SSLEngineResult(
getEngineStatus(), handshakeStatus, 0, 0);
}
if (src.remaining() < recordProtocol.getMinRecordSize()) {
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_UNDERFLOW,
getHandshakeStatus(), 0, 0);
}
try {
src.mark();
// check the destination buffers and count their capacity
int capacity = 0;
for (int i=offset; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy