Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
dghgit committed Jan 18, 2018
2 parents e727ec8 + 1892663 commit ae5d03f
Show file tree
Hide file tree
Showing 23 changed files with 335 additions and 46 deletions.
6 changes: 4 additions & 2 deletions tls/src/main/java/org/bouncycastle/jsse/BCSSLConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ public interface BCSSLConnection
* <a href="https://tools.ietf.org/html/rfc5929">RFC 5929</a> for details.
*
* @param channelBinding
* An IANA-registered "Channel-binding unique prefix" valid for TLS e.g. "tls-unique".
* @return A copy of the channel binding data as a {@link byte[]}.
* An IANA-registered "Channel-binding unique prefix" valid for TLS e.g.
* "tls-unique" or "tls-server-end-point".
* @return A copy of the channel binding data as a {@link byte[]}, or null if the binding is
* unavailable for this connection.
*/
byte[] getChannelBinding(String channelBinding);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ ProvSSLSessionImpl getSessionImpl()

public byte[] getChannelBinding(String channelBinding)
{
if (channelBinding.equals("tls-server-end-point"))
{
return tlsContext.exportChannelBinding(ChannelBinding.tls_server_end_point);
}

if (channelBinding.equals("tls-unique"))
{
return tlsContext.exportChannelBinding(ChannelBinding.tls_unique);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@ public Socket createSocket(String host, int port, InetAddress localHost, int loc

public Socket createSocket(Socket s, InputStream consumed, boolean autoClose) throws IOException
{
/*
* TODO[jsse] "Creates a server mode Socket layered over an existing connected socket,
* and is able to read data which has already been consumed/removed from the Socket's
* underlying InputStream."
*/
throw new UnsupportedOperationException();
return new ProvSSLSocketWrap(context, context.createContextData(), s, consumed, autoClose);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
Expand All @@ -25,36 +26,66 @@ class ProvSSLSocketWrap
extends ProvSSLSocketBase
implements ProvTlsManager
{
private static Socket checkSocket(Socket s) throws SocketException
{
if (s == null)
{
throw new NullPointerException("'s' cannot be null");
}
if (!s.isConnected())
{
throw new SocketException("'s' is not a connected socket");
}
return s;
}

protected final AppDataInput appDataIn = new AppDataInput();
protected final AppDataOutput appDataOut = new AppDataOutput();

protected final ProvSSLContextSpi context;
protected final ContextData contextData;
protected final Socket wrapSocket;
protected final String wrapHost;
protected final int wrapPort;
protected final boolean wrapAutoClose;
protected final InputStream consumed;
protected final String host;
protected final boolean autoClose;
protected final ProvSSLParameters sslParameters;

protected boolean enableSessionCreation = true;
protected boolean useClientMode = true;
protected boolean useClientMode;

protected boolean initialHandshakeBegun = false;
protected TlsProtocol protocol = null;
protected ProvTlsPeer protocolPeer = null;
protected BCSSLConnection connection = null;
protected SSLSession handshakeSession = null;

protected ProvSSLSocketWrap(ProvSSLContextSpi context, ContextData contextData, Socket s, InputStream consumed, boolean autoClose)
throws IOException
{
super();

this.context = context;
this.contextData = contextData;
this.wrapSocket = checkSocket(s);
this.consumed = consumed;
this.host = null;
this.autoClose = autoClose;
this.useClientMode = false;
this.sslParameters = context.getDefaultParameters(!useClientMode);
}

protected ProvSSLSocketWrap(ProvSSLContextSpi context, ContextData contextData, Socket s, String host, int port, boolean autoClose)
throws IOException
{
super();

this.context = context;
this.contextData = contextData;
this.wrapSocket = s;
this.wrapHost = host;
this.wrapPort = port;
this.wrapAutoClose = autoClose;
this.wrapSocket = checkSocket(s);
this.consumed = null;
this.host = host;
this.autoClose = autoClose;
this.useClientMode = true;
this.sslParameters = context.getDefaultParameters(!useClientMode);
}

Expand Down Expand Up @@ -91,7 +122,7 @@ public synchronized void close() throws IOException
@Override
protected void closeSocket() throws IOException
{
if (wrapAutoClose)
if (autoClose)
{
wrapSocket.close();
}
Expand Down Expand Up @@ -456,8 +487,13 @@ public synchronized void startHandshake() throws IOException
{
// TODO[jsse] Check for session to re-use and apply to handshake
// TODO[jsse] Allocate this.handshakeSession and update it during handshake

InputStream input = wrapSocket.getInputStream();
if (consumed != null)
{
input = new SequenceInputStream(consumed, input);
}

OutputStream output = wrapSocket.getOutputStream();

if (this.useClientMode)
Expand All @@ -467,17 +503,17 @@ public synchronized void startHandshake() throws IOException

ProvTlsClient client = new ProvTlsClient(this, sslParameters.copy());
this.protocolPeer = client;

clientProtocol.connect(client);
}
else
{
TlsServerProtocol serverProtocol = new ProvTlsServerProtocol(input, output, socketCloser);
this.protocol = serverProtocol;

ProvTlsServer server = new ProvTlsServer(this, sslParameters.copy());
this.protocolPeer = server;

serverProtocol.accept(server);
}
}
Expand All @@ -496,7 +532,9 @@ public String toString()

public String getPeerHost()
{
return wrapHost;
// TODO[jsse] See SunJSSE for some attempt at implicit host name determination

return host;
}

public int getPeerPort()
Expand Down
15 changes: 14 additions & 1 deletion tls/src/main/java/org/bouncycastle/tls/AbstractTlsContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ public byte[] exportChannelBinding(int channelBinding)
{
switch (channelBinding)
{
case ChannelBinding.tls_server_end_point:
{
byte[] tlsServerEndPoint = getSecurityParameters().getTLSServerEndPoint();
if (tlsServerEndPoint == null)
{
throw new IllegalStateException("'tls-server-end-point' channel binding unavailable before handshake completion");
}
if (tlsServerEndPoint.length < 1)
{
return null;
}
return Arrays.clone(tlsServerEndPoint);
}

case ChannelBinding.tls_unique:
{
byte[] tlsUnique = getSecurityParameters().getTLSUnique();
Expand All @@ -121,7 +135,6 @@ public byte[] exportChannelBinding(int channelBinding)
return Arrays.clone(tlsUnique);
}

case ChannelBinding.tls_server_end_point:
case ChannelBinding.tls_unique_for_telnet:
default:
throw new UnsupportedOperationException();
Expand Down
69 changes: 63 additions & 6 deletions tls/src/main/java/org/bouncycastle/tls/Certificate.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,49 @@ public boolean isEmpty()
*
* @param output the {@link OutputStream} to encode to.
* @throws IOException
* @deprecated
*/
public void encode(OutputStream output)
throws IOException
{
encode(null, output, null);
}

/**
* Encode this {@link Certificate} to an {@link OutputStream}, and optionally calculate the
* "end point hash" (per RFC 5929's tls-server-end-point binding).
*
* @param messageOutput the {@link OutputStream} to encode to.
* @param endPointHashOutput the {@link OutputStream} to write the "end point hash" (or null).
* @throws IOException
*/
public void encode(TlsContext context, OutputStream messageOutput, OutputStream endPointHashOutput)
throws IOException
{
Vector derEncodings = new Vector(this.certificateList.length);

int totalLength = 0;
for (int i = 0; i < this.certificateList.length; ++i)
{
byte[] derEncoding = certificateList[i].getEncoded();
TlsCertificate cert = certificateList[i];
byte[] derEncoding = cert.getEncoded();

if (i == 0 && endPointHashOutput != null)
{
calculateEndPointHash(context, cert, derEncoding, endPointHashOutput);
}

derEncodings.addElement(derEncoding);
totalLength += derEncoding.length + 3;
}

TlsUtils.checkUint24(totalLength);
TlsUtils.writeUint24(totalLength, output);
TlsUtils.writeUint24(totalLength, messageOutput);

for (int i = 0; i < derEncodings.size(); ++i)
{
byte[] derEncoding = (byte[])derEncodings.elementAt(i);
TlsUtils.writeOpaque24(derEncoding, output);
TlsUtils.writeOpaque24(derEncoding, messageOutput);
}
}

Expand All @@ -102,25 +124,50 @@ public void encode(OutputStream output)
* the {@link InputStream} to parse from.
* @return a {@link Certificate} object.
* @throws IOException
* @deprecated
*/
public static Certificate parse(TlsContext context, InputStream input)
throws IOException
{
int totalLength = TlsUtils.readUint24(input);
return parse(context, input, null);
}

/**
* Parse a {@link Certificate} from an {@link InputStream}.
*
* @param context
* the {@link TlsContext} of the current connection.
* @param messageInput
* the {@link InputStream} to parse from.
* @param endPointHashOutput the {@link OutputStream} to write the "end point hash" (or null).
* @return a {@link Certificate} object.
* @throws IOException
*/
public static Certificate parse(TlsContext context, InputStream messageInput, OutputStream endPointHashOutput)
throws IOException
{
int totalLength = TlsUtils.readUint24(messageInput);
if (totalLength == 0)
{
return EMPTY_CHAIN;
}

byte[] certListData = TlsUtils.readFully(totalLength, input);
byte[] certListData = TlsUtils.readFully(totalLength, messageInput);

ByteArrayInputStream buf = new ByteArrayInputStream(certListData);

Vector certificate_list = new Vector();
while (buf.available() > 0)
{
byte[] derEncoding = TlsUtils.readOpaque24(buf);
certificate_list.addElement(context.getCrypto().createCertificate(derEncoding));
TlsCertificate cert = context.getCrypto().createCertificate(derEncoding);

if (certificate_list.isEmpty() && endPointHashOutput != null)
{
calculateEndPointHash(context, cert, derEncoding, endPointHashOutput);
}

certificate_list.addElement(cert);
}

TlsCertificate[] certificateList = new TlsCertificate[certificate_list.size()];
Expand All @@ -131,6 +178,16 @@ public static Certificate parse(TlsContext context, InputStream input)
return new Certificate(certificateList);
}

protected static void calculateEndPointHash(TlsContext context, TlsCertificate cert, byte[] encoding, OutputStream output)
throws IOException
{
byte[] endPointHash = TlsUtils.calculateEndPointHash(context, cert.getSigAlgOID(), encoding);
if (endPointHash != null && endPointHash.length > 0)
{
output.write(endPointHash);
}
}

protected TlsCertificate[] cloneCertificateList()
{
TlsCertificate[] result = new TlsCertificate[certificateList.length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ protected DTLSTransport clientHandshake(ClientHandshakeState state, DTLSRecordLa
if (state.authentication == null)
{
// There was no server certificate message; check it's OK
state.clientContext.getSecurityParameters().tlsServerEndPoint = TlsUtils.EMPTY_BYTES;
state.keyExchange.skipServerCredentials();
}
else
Expand Down Expand Up @@ -298,7 +299,7 @@ protected DTLSTransport clientHandshake(ClientHandshakeState state, DTLSRecordLa
clientCertificate = Certificate.EMPTY_CHAIN;
}

byte[] certificateBody = generateCertificate(clientCertificate);
byte[] certificateBody = generateCertificate(state.clientContext, clientCertificate, null);
handshake.sendMessage(HandshakeType.certificate, certificateBody);
}

Expand Down Expand Up @@ -597,11 +598,14 @@ protected Certificate processServerCertificate(ClientHandshakeState state, byte[
throws IOException
{
ByteArrayInputStream buf = new ByteArrayInputStream(body);
ByteArrayOutputStream endPointHash = new ByteArrayOutputStream();

Certificate serverCertificate = Certificate.parse(state.clientContext, buf);
Certificate serverCertificate = Certificate.parse(state.clientContext, buf, endPointHash);

TlsProtocol.assertEmpty(buf);

state.clientContext.getSecurityParameters().tlsServerEndPoint = endPointHash.toByteArray();

state.authentication = state.client.getAuthentication();
if (state.authentication == null)
{
Expand Down
10 changes: 10 additions & 0 deletions tls/src/main/java/org/bouncycastle/tls/DTLSProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Vector;

Expand Down Expand Up @@ -60,6 +61,7 @@ protected static short evaluateMaxFragmentLengthExtension(boolean resumedSession
return maxFragmentLength;
}

/** @deprecated */
protected static byte[] generateCertificate(Certificate certificate)
throws IOException
{
Expand All @@ -68,6 +70,14 @@ protected static byte[] generateCertificate(Certificate certificate)
return buf.toByteArray();
}

protected static byte[] generateCertificate(TlsContext context, Certificate certificate, OutputStream endPointHash)
throws IOException
{
ByteArrayOutputStream buf = new ByteArrayOutputStream();
certificate.encode(context, buf, endPointHash);
return buf.toByteArray();
}

protected static byte[] generateSupplementalData(Vector supplementalData)
throws IOException
{
Expand Down
Loading

0 comments on commit ae5d03f

Please sign in to comment.