com.mobius.software.iot.dal.crypto.AsyncDtlsClientProtocol Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dtls-async-client Show documentation
Show all versions of dtls-async-client Show documentation
DTLS Java Async Implementation Based on Bouncy Castle
package com.mobius.software.iot.dal.crypto;
/**
* Mobius Software LTD
* Copyright 2018, Mobius Software LTD
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateEncodingException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import org.bouncycastle.crypto.tls.AlertDescription;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.crypto.tls.CipherSuite;
import org.bouncycastle.crypto.tls.CipherType;
import org.bouncycastle.crypto.tls.CompressionMethod;
import org.bouncycastle.crypto.tls.ConnectionEnd;
import org.bouncycastle.crypto.tls.EncryptionAlgorithm;
import org.bouncycastle.crypto.tls.ExporterLabel;
import org.bouncycastle.crypto.tls.HashAlgorithm;
import org.bouncycastle.crypto.tls.MaxFragmentLength;
import org.bouncycastle.crypto.tls.NewSessionTicket;
import org.bouncycastle.crypto.tls.ProtocolVersion;
import org.bouncycastle.crypto.tls.SecurityParameters;
import org.bouncycastle.crypto.tls.SessionParameters;
import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.crypto.tls.SupplementalDataEntry;
import org.bouncycastle.crypto.tls.TlsFatalAlert;
import org.bouncycastle.crypto.tls.TlsHandshakeHash;
import org.bouncycastle.crypto.tls.TlsSignerCredentials;
public class AsyncDtlsClientProtocol implements HandshakeHandler
{
enum State
{
INIT, CLIENT_HELLO_SENT, SERVER_HELLO_RECEIVED, SUPP_DATA_RECEIVED, CERTIFICATE_RECEIVED, CERTIFICATE_STATUS_RECEIVED, SERVER_KEY_EXCHANGE_RECEIVED, CERTIFICATE_REQUEST_RECEIVED, SERVER_HELLO_DONE, FINISH_SENT, SESSION_TICKET_RECEIVED,ENDED
}
private AsyncDtlsClientState clientState;
private AsyncDtlsRecordLayer recordLayer;
private State handshakeState=State.INIT;
private Certificate serverCertificate;
private short sequence=0;
private HandshakeHandler parentHandler;
private DtlsStateHandler handler;
private Channel channel;
private InetSocketAddress remoteAddress;
public AsyncDtlsClientProtocol(AsyncDtlsClient client,SecureRandom secureRandom,Channel channel,HandshakeHandler parentHandler,DtlsStateHandler handler,InetSocketAddress address) throws UnrecoverableKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, IOException
{
this.parentHandler=parentHandler;
this.handler=handler;
this.channel=channel;
this.remoteAddress=address;
AsyncDtlsSecurityParameters securityParameters = new AsyncDtlsSecurityParameters();
securityParameters.setEntity(ConnectionEnd.client);
clientState = new AsyncDtlsClientState();
clientState.setClient(client);
clientState.setClientContext(new AsyncDtlsClientContext(secureRandom, securityParameters));
securityParameters.setClientRandom(DtlsHelper.createRandomBlock(client.shouldUseGMTUnixTime(),clientState.getClientContext().getNonceRandomGenerator()));
client.initClient(clientState.getClientContext());
clientState.setHandshakeHash(new DeferredHash());
clientState.getHandshakeHash().init(clientState.getClientContext());
recordLayer = new AsyncDtlsRecordLayer(clientState.getHandshakeHash(), this, channel,clientState.getClientContext(), client, address);
}
public Certificate getServerCertificate()
{
return this.serverCertificate;
}
public void sendAlert(short alertLevel,short alertDescription,String message,Throwable cause) throws IOException
{
recordLayer.sendAlert(alertLevel, alertDescription, message, cause);
}
public void sendPacket(ByteBuf data) throws IOException
{
recordLayer.send(data);
}
public List receivePacket(ByteBuf data) throws IOException
{
return recordLayer.receive(data);
}
@SuppressWarnings("unchecked")
public void initHandshake(byte[] cookie) throws IOException
{
SecurityParameters securityParameters = clientState.getClientContext().getSecurityParameters();
ProtocolVersion client_version = clientState.getClient().getClientVersion();
if (!client_version.isDTLS())
throw new TlsFatalAlert(AlertDescription.internal_error);
AsyncDtlsClientContext context = clientState.getClientContext();
context.setClientVersion(client_version);
boolean fallback = clientState.getClient().isFallback();
//Cipher suites
clientState.setOfferedCipherSuites(clientState.getClient().getCipherSuites());
// Integer -> byte[]
clientState.setClientExtensions(clientState.getClient().getClientExtensions());
byte[] renegExtData = clientState.getClientExtensions().get(DtlsHelper.EXT_RenegotiationInfo);
boolean noRenegExt = (null == renegExtData);
boolean noRenegSCSV = true;
for(int i=0;i0)
{
offeredCipherSuites=new int[clientState.getOfferedCipherSuites().length + additionalCount];
System.arraycopy(clientState.getOfferedCipherSuites(), 0, offeredCipherSuites, 0, clientState.getOfferedCipherSuites().length);
if (noRenegExt && noRenegSCSV)
offeredCipherSuites[clientState.getOfferedCipherSuites().length]=CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
if (fallback && !tlsFallbackFound)
offeredCipherSuites[offeredCipherSuites.length-1]=CipherSuite.TLS_FALLBACK_SCSV;
}
clientState.setOfferedCompressionMethods(new short[]{ CompressionMethod._null });
byte[] session_id = DtlsHelper.EMPTY_BYTES;
if (clientState.getTlsSession() != null)
{
session_id = clientState.getTlsSession().getSessionID();
if (session_id == null || session_id.length > 32)
session_id = DtlsHelper.EMPTY_BYTES;
}
int totalLength = 8 + securityParameters.getClientRandom().length + session_id.length + 2*offeredCipherSuites.length + clientState.getOfferedCompressionMethods().length + DtlsHelper.calculateExtensionsLength(clientState.getClientExtensions());
int capacity = DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + totalLength;
ByteBuf data=Unpooled.buffer(capacity);
short currSequence=sequence++;
DtlsHelper.writeHandshakeHeader(currSequence,MessageType.CLIENT_HELLO,data,totalLength);
data.writeByte(client_version.getMajorVersion());
data.writeByte(client_version.getMinorVersion());
data.writeBytes(securityParameters.getClientRandom());
// Session ID
data.writeByte(session_id.length);
data.writeBytes(session_id);
if(cookie!=null)
{
data.writeByte(cookie.length);
data.writeBytes(cookie);
}
//Cookie
data.writeBytes(DtlsHelper.EMPTY_BYTES_WITH_LENGTH);
data.writeShort(2*offeredCipherSuites.length);
for(int i=0;i= 0)
{
if (!MaxFragmentLength.isValid(maxFragmentLength))
throw new TlsFatalAlert(AlertDescription.internal_error);
int plainTextLimit = 1 << (8 + maxFragmentLength);
recordLayer.setPlaintextLimit(plainTextLimit);
}
if (clientState.isResumedSession())
{
byte[] masterSecret=new byte[clientState.getSessionParameters().getMasterSecret().length];
System.arraycopy(clientState.getSessionParameters().getMasterSecret(), 0, masterSecret, 0, masterSecret.length);
clientState.getClientContext().getSecurityParameters().setMasterSecret(masterSecret);
recordLayer.initPendingEpoch(clientState.getClient().getCipher());
}
else
{
if (clientState.getSessionParameters() != null)
{
clientState.getSessionParameters().clear();
clientState.setSessionParameters(null);
}
if (clientState.getTlsSession() != null)
{
clientState.getTlsSession().invalidate();
clientState.setTlsSession(null);
}
if (clientState.getSelectedSessionID().length > 0)
clientState.setTlsSession(new AsyncDtlsSessionImpl(clientState.getSelectedSessionID(), null));
}
handshakeState=State.SERVER_HELLO_RECEIVED;
break;
case SUPPLEMENTAL_DATA:
if(handshakeState!=State.SERVER_HELLO_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processServerSupplementalData(data);
handshakeState=State.SUPP_DATA_RECEIVED;
break;
case CERTIFICATE:
if(handshakeState==State.SERVER_HELLO_RECEIVED)
{
clientState.getClient().processServerSupplementalData(null);
handshakeState = State.SUPP_DATA_RECEIVED;
}
if(handshakeState!=State.SUPP_DATA_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
clientState.setKeyExchange(clientState.getClient().getKeyExchange());
clientState.getKeyExchange().init(clientState.getClientContext());
processServerCertificate(data);
handshakeState=State.CERTIFICATE_RECEIVED;
break;
case CERTIFICATE_STATUS:
if(handshakeState==State.SERVER_HELLO_RECEIVED)
{
clientState.getClient().processServerSupplementalData(null);
handshakeState = State.SUPP_DATA_RECEIVED;
}
if(handshakeState==State.SUPP_DATA_RECEIVED)
{
clientState.setKeyExchange(clientState.getClient().getKeyExchange());
clientState.getKeyExchange().init(clientState.getClientContext());
clientState.getKeyExchange().skipServerCredentials();
handshakeState = State.CERTIFICATE_RECEIVED;
}
if(handshakeState!=State.CERTIFICATE_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processCertificateStatus(data);
handshakeState=State.CERTIFICATE_STATUS_RECEIVED;
break;
case SERVER_KEY_EXCHANGE:
if(handshakeState==State.SERVER_HELLO_RECEIVED)
{
clientState.getClient().processServerSupplementalData(null);
handshakeState = State.SUPP_DATA_RECEIVED;
}
if(handshakeState==State.SUPP_DATA_RECEIVED)
{
clientState.setKeyExchange(clientState.getClient().getKeyExchange());
clientState.getKeyExchange().init(clientState.getClientContext());
clientState.getKeyExchange().skipServerCredentials();
handshakeState = State.CERTIFICATE_RECEIVED;
}
if(handshakeState == State.CERTIFICATE_RECEIVED)
handshakeState=State.CERTIFICATE_STATUS_RECEIVED;
if(handshakeState!=State.CERTIFICATE_STATUS_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processServerKeyExchange(data);
handshakeState=State.SERVER_KEY_EXCHANGE_RECEIVED;
break;
case CERTIFICATE_REQUEST:
if(handshakeState==State.SERVER_HELLO_RECEIVED)
{
clientState.getClient().processServerSupplementalData(null);
handshakeState = State.SUPP_DATA_RECEIVED;
}
if(handshakeState==State.SUPP_DATA_RECEIVED)
{
clientState.setKeyExchange(clientState.getClient().getKeyExchange());
clientState.getKeyExchange().init(clientState.getClientContext());
clientState.getKeyExchange().skipServerCredentials();
handshakeState = State.CERTIFICATE_RECEIVED;
}
if(handshakeState == State.CERTIFICATE_RECEIVED)
handshakeState=State.CERTIFICATE_STATUS_RECEIVED;
if(handshakeState == State.CERTIFICATE_STATUS_RECEIVED)
{
clientState.getKeyExchange().skipServerKeyExchange();
handshakeState=State.SERVER_KEY_EXCHANGE_RECEIVED;
}
if(handshakeState!=State.SERVER_KEY_EXCHANGE_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processCertificateRequest(data);
handshakeState=State.CERTIFICATE_REQUEST_RECEIVED;
break;
case SERVER_HELLO_DONE:
if(handshakeState==State.SERVER_HELLO_RECEIVED)
{
clientState.getClient().processServerSupplementalData(null);
handshakeState = State.SUPP_DATA_RECEIVED;
}
if(handshakeState==State.SUPP_DATA_RECEIVED)
{
clientState.setKeyExchange(clientState.getClient().getKeyExchange());
clientState.getKeyExchange().init(clientState.getClientContext());
clientState.getKeyExchange().skipServerCredentials();
handshakeState = State.CERTIFICATE_RECEIVED;
}
if(handshakeState == State.CERTIFICATE_RECEIVED)
handshakeState=State.CERTIFICATE_STATUS_RECEIVED;
if(handshakeState == State.CERTIFICATE_STATUS_RECEIVED)
{
clientState.getKeyExchange().skipServerKeyExchange();
handshakeState=State.SERVER_KEY_EXCHANGE_RECEIVED;
}
if(handshakeState == State.SERVER_KEY_EXCHANGE_RECEIVED)
handshakeState=State.CERTIFICATE_REQUEST_RECEIVED;
if(handshakeState!=State.CERTIFICATE_REQUEST_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processServerHelloDone(data);
handshakeState=State.SERVER_HELLO_DONE;
break;
case SESSION_TICKET:
if(handshakeState!=State.FINISH_SENT || !clientState.isExpectSessionTicket())
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processNewSessionTicket(data);
handshakeState=State.SESSION_TICKET_RECEIVED;
break;
case FINISHED:
if(handshakeState!=State.FINISH_SENT && handshakeState!=State.SESSION_TICKET_RECEIVED && handshakeState!=State.SERVER_HELLO_RECEIVED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
if(handshakeState==State.FINISH_SENT && clientState.isExpectSessionTicket())
throw new TlsFatalAlert(AlertDescription.unexpected_message);
if(handshakeState==State.SERVER_HELLO_RECEIVED && clientState.isResumedSession())
throw new TlsFatalAlert(AlertDescription.unexpected_message);
processFinished(data);
break;
default:
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
@Override
public void postProcessHandshake(MessageType messageType, ByteBuf data) throws IOException
{
//not throwing exception since already handled in handleHandshake
if(parentHandler!=null)
parentHandler.postProcessHandshake(messageType, data);
switch(messageType)
{
case SERVER_HELLO_DONE:
postProcessServerHelloDone();
handshakeState=State.FINISH_SENT;
break;
case FINISHED:
postProcessFinished();
break;
default:
break;
}
}
private void processHelloVerifyRequest(ByteBuf body) throws IOException
{
ProtocolVersion recordLayerVersion = recordLayer.getReadVersion();
ProtocolVersion client_version = clientState.getClientContext().getClientVersion();
if (!recordLayerVersion.isEqualOrEarlierVersionOf(client_version))
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
recordLayer.setReadVersion(null);
ProtocolVersion server_version = ProtocolVersion.get(body.readByte() & 0xFF, body.readByte() & 0xFF);
byte[] cookie = new byte[body.readByte()];
body.readBytes(cookie);
if (!server_version.isEqualOrEarlierVersionOf(clientState.getClientContext().getClientVersion()))
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
if (!ProtocolVersion.DTLSv12.isEqualOrEarlierVersionOf(server_version) && cookie.length > 32)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
clientState.getHandshakeHash().reset();
initHandshake(cookie);
}
@SuppressWarnings("unchecked")
private void processServerHello(ByteBuf body) throws IOException
{
ProtocolVersion recordLayerVersion = recordLayer.getReadVersion();
reportServerVersion(recordLayerVersion);
recordLayer.setWriteVersion(recordLayerVersion);
AsyncDtlsSecurityParameters securityParameters = clientState.getClientContext().getSecurityParameters();
ProtocolVersion server_version = ProtocolVersion.get(body.readByte() & 0xFF, body.readByte() & 0xFF);
reportServerVersion(server_version);
byte[] serverRandom=new byte[32];
body.readBytes(serverRandom);
securityParameters.setServerRandom(serverRandom);
byte[] selectedSessionID=new byte[body.readUnsignedByte()];
if(selectedSessionID.length>0)
body.readBytes(selectedSessionID);
clientState.setSelectedSessionID(selectedSessionID);
if (selectedSessionID.length > 32)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
clientState.getClient().notifySessionID(selectedSessionID);
clientState.setResumedSession(selectedSessionID.length > 0 && clientState.getTlsSession() != null && Arrays.equals(clientState.getSelectedSessionID(), clientState.getTlsSession().getSessionID()));
int selectedCipherSuite = body.readUnsignedShort();
Boolean inOfferedCipherSuites=false;
for(int i=0;i e = clientState.getServerExtensions().keys();
while (e.hasMoreElements())
{
Integer extType = (Integer)e.nextElement();
if (extType.equals(DtlsHelper.EXT_RenegotiationInfo))
continue;
if (clientState.getClientExtensions().get(extType) == null)
throw new TlsFatalAlert(AlertDescription.unsupported_extension);
}
}
byte[] renegExtData = clientState.getServerExtensions().get(DtlsHelper.EXT_RenegotiationInfo);
if (renegExtData != null)
{
clientState.setSecure_renegotiation(true);
if (!Arrays.equals(renegExtData,DtlsHelper.EMPTY_BYTES_WITH_LENGTH))
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
clientState.getClient().notifySecureRenegotiation(clientState.isSecure_renegotiation());
Hashtable sessionClientExtensions = clientState.getClientExtensions();
Hashtable sessionServerExtensions = clientState.getServerExtensions();
if (clientState.isResumedSession())
{
if (selectedCipherSuite != clientState.getSessionParameters().getCipherSuite() || selectedCompressionMethod != clientState.getSessionParameters().getCompressionAlgorithm())
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
sessionClientExtensions = null;
sessionServerExtensions = clientState.getSessionParameters().readServerExtensions();
}
securityParameters.setCipherSuite(selectedCipherSuite);
securityParameters.setCompressionAlgorithm(selectedCompressionMethod);
if (sessionServerExtensions != null)
{
byte[] encryptThenMac=sessionServerExtensions.get(DtlsHelper.EXT_encrypt_then_mac);
if(encryptThenMac!=null && encryptThenMac.length>0)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
boolean serverSentEncryptThenMAC = encryptThenMac!=null;
if (serverSentEncryptThenMAC && DtlsHelper.getCipherType(securityParameters.getCipherSuite())!=CipherType.block)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
securityParameters.setEncryptThenMAC(serverSentEncryptThenMAC);
byte[] extendedMacSecret=sessionServerExtensions.get(DtlsHelper.EXT_extended_master_secret);
if(extendedMacSecret!=null && extendedMacSecret.length>0)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
securityParameters.setExtendedMasterSecret(extendedMacSecret!=null);
securityParameters.setMaxFragmentLength(DtlsHelper.evaluateMaxFragmentLengthExtension(clientState.isResumedSession(),sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter));
byte[] truncatedHMAC=sessionServerExtensions.get(DtlsHelper.EXT_truncated_hmac);
if(truncatedHMAC!=null && truncatedHMAC.length>0)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
securityParameters.setTruncatedHMac(truncatedHMAC!=null);
byte[] statusRequest=sessionServerExtensions.get(DtlsHelper.EXT_status_request);
if(statusRequest!=null && statusRequest.length>0)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
clientState.setAllowCertificateStatus(!clientState.isResumedSession() && statusRequest!=null);
byte[] sessionTicket=sessionServerExtensions.get(DtlsHelper.EXT_SessionTicket);
if(sessionTicket!=null && sessionTicket.length>0)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
clientState.setExpectSessionTicket(!clientState.isResumedSession() && sessionTicket!=null);
}
if (sessionClientExtensions != null)
clientState.getClient().processServerExtensions(sessionServerExtensions);
securityParameters.setPrfAlgorithm(DtlsHelper.getPRFAlgorithm(clientState.getClientContext().getServerVersion(),securityParameters.getCipherSuite()));
securityParameters.setVerifyDataLength(12);
}
private void processServerSupplementalData(ByteBuf body) throws IOException
{
Vector serverSupplementalData = DtlsHelper.readSupplementalData(body);
clientState.getClient().processServerSupplementalData(serverSupplementalData);
}
private void processServerCertificate(ByteBuf data) throws IOException
{
serverCertificate = DtlsHelper.parseCertificate(data);
clientState.getKeyExchange().processServerCertificate(serverCertificate);
clientState.setAuthentication(clientState.getClient().getAuthentication());
clientState.getAuthentication().notifyServerCertificate(serverCertificate);
}
private void processCertificateStatus(ByteBuf data) throws IOException
{
if (!clientState.isAllowCertificateStatus())
throw new TlsFatalAlert(AlertDescription.unexpected_message);
clientState.setCertificateStatus(DtlsHelper.parseCertificateStatus(data));
}
private void processServerKeyExchange(ByteBuf body) throws IOException
{
//can not parse with byte buffer , needs input stream
byte[] backedData=new byte[body.readableBytes()];
body.readBytes(backedData);
ByteArrayInputStream buf = new ByteArrayInputStream(backedData);
clientState.getKeyExchange().processServerKeyExchange(buf);
}
private void processCertificateRequest(ByteBuf body) throws IOException
{
if (clientState.getAuthentication() == null)
throw new TlsFatalAlert(AlertDescription.handshake_failure);
clientState.setCertificateRequest(AsyncCertificateRequest.parse(clientState.getClientContext().getServerVersion(), body));
clientState.getKeyExchange().validateCertificateRequest(clientState.getCertificateRequest());
if (clientState.getCertificateRequest().getSupportedSignatureAlgorithms() != null)
{
for (int i = 0; i < clientState.getCertificateRequest().getSupportedSignatureAlgorithms().size(); ++i)
{
SignatureAndHashAlgorithm signatureAndHashAlgorithm = (SignatureAndHashAlgorithm)clientState.getCertificateRequest().getSupportedSignatureAlgorithms().elementAt(i);
short hashAlgorithm = signatureAndHashAlgorithm.getHash();
if (!HashAlgorithm.isPrivate(hashAlgorithm))
clientState.getHandshakeHash().trackHashAlgorithm(hashAlgorithm);
}
}
}
private void processServerHelloDone(ByteBuf body) throws IOException
{
if (body.readableBytes() != 0)
throw new TlsFatalAlert(AlertDescription.decode_error);
clientState.getHandshakeHash().sealHashAlgorithms();
}
private void processNewSessionTicket(ByteBuf body) throws IOException
{
long ticketLifetimeHint = body.readUnsignedInt();
byte[] ticket = new byte[body.readUnsignedShort()];
body.readBytes(body);
NewSessionTicket newSessionTicket = new NewSessionTicket(ticketLifetimeHint, ticket);
clientState.getClient().notifyNewSessionTicket(newSessionTicket);
}
private void processFinished(ByteBuf body) throws IOException
{
byte[] expectedClientVerifyData = DtlsHelper.calculateVerifyData(clientState.getClientContext(), ExporterLabel.server_finished,DtlsHelper.getCurrentPRFHash(clientState.getClientContext(), clientState.getHandshakeHash(), null));
if(body.readableBytes()!=expectedClientVerifyData.length)
throw new TlsFatalAlert(AlertDescription.handshake_failure);
byte[] serverVerifyData=new byte[body.readableBytes()];
body.readBytes(serverVerifyData);
if(!Arrays.equals(serverVerifyData, expectedClientVerifyData))
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
private void reportServerVersion(ProtocolVersion server_version) throws IOException
{
ProtocolVersion currentServerVersion = clientState.getClientContext().getServerVersion();
if (null == currentServerVersion)
{
clientState.getClientContext().setServerVersion(server_version);
clientState.getClient().notifyServerVersion(server_version);
}
else if (!currentServerVersion.equals(server_version))
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}