![JAR search and dependency download from the Maven repository](/logo.png)
net.jradius.tls.DefaultTlsClient Maven / Gradle / Ivy
The newest version!
package net.jradius.tls;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
public class DefaultTlsClient implements TlsClient
{
// TODO Add runtime support for this check?
/*
* RFC 2246 9. In the absence of an application profile standard specifying otherwise,
* a TLS compliant application MUST implement the cipher suite
* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.
*/
private static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
private static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
private static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
private static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
private static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
// RFC 3268
private static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
private static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
private static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
private static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
private static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
private static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
private static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
private static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
private static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
private static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
// RFC 4279
// private static final int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
// private static final int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
// private static final int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
// private static final int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
// private static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
// private static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
// private static final int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
// private static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
// private static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
// RFC 5054
private static final int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
private static final int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
private static final int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
private static final int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
private static final int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
private static final int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
private static final int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
private static final int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
private static final int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
private CertificateVerifyer verifyer;
private TlsProtocolHandler handler;
// (Optional) details for client-side authentication
private Certificate clientCert = new Certificate(new X509CertificateStructure[0]);
private AsymmetricKeyParameter clientPrivateKey = null;
private TlsSigner clientSigner = null;
private int selectedCipherSuite;
public DefaultTlsClient(CertificateVerifyer verifyer)
{
this.verifyer = verifyer;
}
public void enableClientAuthentication(Certificate clientCertificate,
AsymmetricKeyParameter clientPrivateKey)
{
if (clientCertificate == null)
{
throw new IllegalArgumentException("'clientCertificate' cannot be null");
}
if (clientCertificate.certs.length == 0)
{
throw new IllegalArgumentException("'clientCertificate' cannot be empty");
}
if (clientPrivateKey == null)
{
throw new IllegalArgumentException("'clientPrivateKey' cannot be null");
}
if (!clientPrivateKey.isPrivate())
{
throw new IllegalArgumentException("'clientPrivateKey' must be private");
}
if (clientPrivateKey instanceof RSAKeyParameters)
{
clientSigner = new TlsRSASigner();
}
else if (clientPrivateKey instanceof DSAPrivateKeyParameters)
{
clientSigner = new TlsDSSSigner();
}
else
{
throw new IllegalArgumentException("'clientPrivateKey' type not supported: "
+ clientPrivateKey.getClass().getName());
}
this.clientCert = clientCertificate;
this.clientPrivateKey = clientPrivateKey;
}
public void init(TlsProtocolHandler handler)
{
this.handler = handler;
}
public int[] getCipherSuites()
{
return new int[] {
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_3DES_EDE_CBC_SHA,
// TLS_DH_RSA_WITH_AES_256_CBC_SHA,
// TLS_DH_DSS_WITH_AES_256_CBC_SHA,
// TLS_DH_RSA_WITH_AES_128_CBC_SHA,
// TLS_DH_DSS_WITH_AES_128_CBC_SHA,
// TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
// TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
// TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
// TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
// TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
// TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
// TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
// TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
// TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
// TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
// TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
};
}
public Hashtable generateClientExtensions()
{
// TODO[SRP]
// Hashtable clientExtensions = new Hashtable();
// ByteArrayOutputStream srpData = new ByteArrayOutputStream();
// TlsUtils.writeOpaque8(SRP_identity, srpData);
//
// // TODO[SRP] RFC5054 2.8.1: ExtensionType.srp = 12
// clientExtensions.put(Integer.valueOf(12), srpData.toByteArray());
// return clientExtensions;
return null;
}
public void notifySessionID(byte[] sessionID)
{
// Currently ignored
}
public void notifySelectedCipherSuite(int selectedCipherSuite)
{
this.selectedCipherSuite = selectedCipherSuite;
}
public void processServerExtensions(Hashtable serverExtensions)
{
// TODO Validate/process serverExtensions (via client?)
// TODO[SRP]
}
public TlsKeyExchange createKeyExchange() throws IOException
{
switch (selectedCipherSuite)
{
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_RSA_WITH_AES_128_CBC_SHA:
case TLS_RSA_WITH_AES_256_CBC_SHA:
return createRSAKeyExchange();
case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DH_DSS);
case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DH_RSA);
case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DHE_DSS);
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
return createDHKeyExchange(TlsKeyExchange.KE_DHE_RSA);
case TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP);
case TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP_RSA);
case TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
return createSRPExchange(TlsKeyExchange.KE_SRP_DSS);
default:
/*
* Note: internal error here; the TlsProtocolHandler verifies that the
* server-selected cipher suite was in the list of client-offered cipher
* suites, so if we now can't produce an implementation, we shouldn't have
* offered it!
*/
handler.failWithError(TlsProtocolHandler.AL_fatal,
TlsProtocolHandler.AP_internal_error);
return null; // Unreachable!
}
}
public void processServerCertificateRequest(byte[] certificateTypes, List certificateAuthorities)
{
// TODO There shouldn't be a certificate request for SRP
// TODO Use provided info to choose a certificate in getCertificate()
}
public byte[] generateCertificateSignature(byte[] md5andsha1) throws IOException
{
if (clientSigner == null)
{
return null;
}
try
{
return clientSigner.calculateRawSignature(clientPrivateKey, md5andsha1);
}
catch (CryptoException e)
{
handler.failWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_internal_error);
return null;
}
}
public Certificate getCertificate()
{
return clientCert;
}
public TlsCipher createCipher(SecurityParameters securityParameters) throws IOException
{
switch (selectedCipherSuite)
{
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
return createDESedeCipher(24, securityParameters);
case TLS_RSA_WITH_AES_128_CBC_SHA:
case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
return createAESCipher(16, securityParameters);
case TLS_RSA_WITH_AES_256_CBC_SHA:
case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
case TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
case TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
case TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
return createAESCipher(32, securityParameters);
default:
/*
* Note: internal error here; the TlsProtocolHandler verifies that the
* server-selected cipher suite was in the list of client-offered cipher
* suites, so if we now can't produce an implementation, we shouldn't have
* offered it!
*/
handler.failWithError(TlsProtocolHandler.AL_fatal,
TlsProtocolHandler.AP_internal_error);
return null; // Unreachable!
}
}
private TlsKeyExchange createDHKeyExchange(short keyExchange)
{
return new TlsDHKeyExchange(handler, verifyer, keyExchange);
}
private TlsKeyExchange createRSAKeyExchange()
{
return new TlsRSAKeyExchange(handler, verifyer);
}
private TlsKeyExchange createSRPExchange(short keyExchange)
{
return new TlsSRPKeyExchange(handler, verifyer, keyExchange);
}
private TlsCipher createAESCipher(int cipherKeySize, SecurityParameters securityParameters)
{
return new TlsBlockCipher(handler, createAESBlockCipher(), createAESBlockCipher(),
new SHA1Digest(), new SHA1Digest(), cipherKeySize, securityParameters);
}
private TlsCipher createDESedeCipher(int cipherKeySize, SecurityParameters securityParameters)
{
return new TlsBlockCipher(handler, createDESedeBlockCipher(), createDESedeBlockCipher(),
new SHA1Digest(), new SHA1Digest(), cipherKeySize, securityParameters);
}
private static BlockCipher createAESBlockCipher()
{
return new CBCBlockCipher(new AESFastEngine());
}
private static BlockCipher createDESedeBlockCipher()
{
return new CBCBlockCipher(new DESedeEngine());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy