package org.bouncycastle.crypto.tls;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
public abstract class AbstractTlsClient
extends AbstractTlsPeer
implements TlsClient
{
protected TlsCipherFactory cipherFactory;
protected TlsClientContext context;
protected Vector supportedSignatureAlgorithms;
protected int[] namedCurves;
protected short[] clientECPointFormats, serverECPointFormats;
protected int selectedCipherSuite;
protected short selectedCompressionMethod;
public AbstractTlsClient()
{
this(new DefaultTlsCipherFactory());
}
public AbstractTlsClient(TlsCipherFactory cipherFactory)
{
this.cipherFactory = cipherFactory;
}
protected boolean allowUnexpectedServerExtension(Integer extensionType, byte[] extensionData)
throws IOException
{
switch (extensionType.intValue())
{
case ExtensionType.elliptic_curves:
TlsECCUtils.readSupportedEllipticCurvesExtension(extensionData);
return true;
case ExtensionType.ec_point_formats:
TlsECCUtils.readSupportedPointFormatsExtension(extensionData);
return true;
default:
return false;
}
}
protected void checkForUnexpectedServerExtension(Hashtable serverExtensions, Integer extensionType)
throws IOException
{
byte[] extensionData = TlsUtils.getExtensionData(serverExtensions, extensionType);
if (extensionData != null && !allowUnexpectedServerExtension(extensionType, extensionData))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
public void init(TlsClientContext context)
{
this.context = context;
}
public TlsSession getSessionToResume()
{
return null;
}
public ProtocolVersion getClientHelloRecordLayerVersion()
{
return getClientVersion();
}
public ProtocolVersion getClientVersion()
{
return ProtocolVersion.TLSv12;
}
public boolean isFallback()
{
return false;
}
public Hashtable getClientExtensions()
throws IOException
{
Hashtable clientExtensions = null;
ProtocolVersion clientVersion = context.getClientVersion();
if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
{
this.supportedSignatureAlgorithms = TlsUtils.getDefaultSupportedSignatureAlgorithms();
clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions);
TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms);
}
if (TlsECCUtils.containsECCCipherSuites(getCipherSuites()))
{
this.namedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 };
this.clientECPointFormats = new short[]{ ECPointFormat.uncompressed,
ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions);
TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves);
TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats);
}
return clientExtensions;
}
public ProtocolVersion getMinimumVersion()
{
return ProtocolVersion.TLSv10;
}
public void notifyServerVersion(ProtocolVersion serverVersion)
throws IOException
{
if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion))
{
throw new TlsFatalAlert(AlertDescription.protocol_version);
}
}
public short[] getCompressionMethods()
{
return new short[]{CompressionMethod._null};
}
public void notifySessionID(byte[] sessionID)
{
}
public void notifySelectedCipherSuite(int selectedCipherSuite)
{
this.selectedCipherSuite = selectedCipherSuite;
}
public void notifySelectedCompressionMethod(short selectedCompressionMethod)
{
this.selectedCompressionMethod = selectedCompressionMethod;
}
public void processServerExtensions(Hashtable serverExtensions)
throws IOException
{
if (serverExtensions != null)
{
checkForUnexpectedServerExtension(serverExtensions, TlsUtils.EXT_signature_algorithms);
checkForUnexpectedServerExtension(serverExtensions, TlsECCUtils.EXT_elliptic_curves);
if (TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
{
this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions);
}
else
{
checkForUnexpectedServerExtension(serverExtensions, TlsECCUtils.EXT_ec_point_formats);
}
checkForUnexpectedServerExtension(serverExtensions, TlsExtensionsUtils.EXT_padding);
}
}
public void processServerSupplementalData(Vector serverSupplementalData)
throws IOException
{
if (serverSupplementalData != null)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
public Vector getClientSupplementalData()
throws IOException
{
return null;
}
public TlsCompression getCompression()
throws IOException
{
switch (selectedCompressionMethod)
{
case CompressionMethod._null:
return new TlsNullCompression();
default:
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
public TlsCipher getCipher()
throws IOException
{
int encryptionAlgorithm = TlsUtils.getEncryptionAlgorithm(selectedCipherSuite);
int macAlgorithm = TlsUtils.getMACAlgorithm(selectedCipherSuite);
return cipherFactory.createCipher(context, encryptionAlgorithm, macAlgorithm);
}
public void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
throws IOException
{
}
}