![JAR search and dependency download from the Maven repository](/logo.png)
org.spongycastle.tls.TlsDHKeyExchange Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bctls-jdk15on Show documentation
Show all versions of bctls-jdk15on Show documentation
Spongy Castle is a package-rename (org.bouncycastle.* to org.spongycastle.*) of Bouncy Castle
intended for the Android platform. Android unfortunately ships with a stripped-down version of
Bouncy Castle, which prevents easy upgrades - Spongy Castle overcomes this and provides a full,
up-to-date version of the Bouncy Castle cryptographic libs.
The newest version!
package org.spongycastle.tls;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import org.spongycastle.tls.crypto.TlsAgreement;
import org.spongycastle.tls.crypto.TlsCertificate;
import org.spongycastle.tls.crypto.TlsDHConfig;
import org.spongycastle.tls.crypto.TlsSecret;
/**
* (D)TLS DH key exchange.
*/
public class TlsDHKeyExchange
extends AbstractTlsKeyExchange
{
private static int checkKeyExchange(int keyExchange)
{
switch (keyExchange)
{
case KeyExchangeAlgorithm.DH_anon:
case KeyExchangeAlgorithm.DH_DSS:
case KeyExchangeAlgorithm.DH_RSA:
case KeyExchangeAlgorithm.DHE_DSS:
case KeyExchangeAlgorithm.DHE_RSA:
return keyExchange;
default:
throw new IllegalArgumentException("unsupported key exchange algorithm");
}
}
protected TlsDHConfigVerifier dhConfigVerifier;
protected TlsCredentialedAgreement agreementCredentials;
protected TlsCertificate dhPeerCertificate;
protected TlsDHConfig dhConfig;
protected TlsAgreement agreement;
public TlsDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsDHConfigVerifier dhConfigVerifier)
{
this(keyExchange, supportedSignatureAlgorithms, dhConfigVerifier, null);
}
public TlsDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsDHConfig dhConfig)
{
this(keyExchange, supportedSignatureAlgorithms, null, dhConfig);
}
private TlsDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsDHConfigVerifier dhConfigVerifier,
TlsDHConfig dhConfig)
{
super(checkKeyExchange(keyExchange), supportedSignatureAlgorithms);
this.dhConfigVerifier = dhConfigVerifier;
this.dhConfig = dhConfig;
}
public void skipServerCredentials() throws IOException
{
if (keyExchange != KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
public void processServerCredentials(TlsCredentials serverCredentials) throws IOException
{
if (keyExchange == KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
if (!(serverCredentials instanceof TlsCredentialedAgreement))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
this.agreementCredentials = (TlsCredentialedAgreement)serverCredentials;
}
public void processServerCertificate(Certificate serverCertificate) throws IOException
{
if (keyExchange == KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
checkServerCertSigAlg(serverCertificate);
this.dhPeerCertificate = validatePeerCertificate(ConnectionEnd.server, serverCertificate);
}
public boolean requiresServerKeyExchange()
{
switch (keyExchange)
{
case KeyExchangeAlgorithm.DH_anon:
case KeyExchangeAlgorithm.DHE_DSS:
case KeyExchangeAlgorithm.DHE_RSA:
return true;
default:
return false;
}
}
public byte[] generateServerKeyExchange() throws IOException
{
if (!requiresServerKeyExchange())
{
return null;
}
// DH_anon is handled here, DHE_* in a subclass
ByteArrayOutputStream buf = new ByteArrayOutputStream();
TlsDHUtils.writeDHConfig(dhConfig, buf);
this.agreement = context.getCrypto().createDHDomain(dhConfig).createDH();
generateEphemeral(buf);
return buf.toByteArray();
}
public void processServerKeyExchange(InputStream input) throws IOException
{
if (!requiresServerKeyExchange())
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
// DH_anon is handled here, DHE_* in a subclass
this.dhConfig = TlsDHUtils.receiveDHConfig(dhConfigVerifier, input);
byte[] y = TlsUtils.readOpaque16(input);
this.agreement = context.getCrypto().createDHDomain(dhConfig).createDH();
processEphemeral(y);
}
public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
{
if (keyExchange == KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
short[] types = certificateRequest.getCertificateTypes();
for (int i = 0; i < types.length; ++i)
{
switch (types[i])
{
case ClientCertificateType.dss_fixed_dh:
case ClientCertificateType.rsa_fixed_dh:
break;
default:
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
}
public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
{
if (keyExchange == KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
if (clientCredentials instanceof TlsCredentialedAgreement)
{
this.agreementCredentials = (TlsCredentialedAgreement)clientCredentials;
// TODO Check that the client certificate's domain parameters match the server's?
}
else
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
public void generateClientKeyExchange(OutputStream output) throws IOException
{
/*
* RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
* key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
* Exchange message will be sent, but will be empty.
*/
if (agreementCredentials == null)
{
generateEphemeral(output);
}
}
public void processClientCertificate(Certificate clientCertificate) throws IOException
{
if (keyExchange == KeyExchangeAlgorithm.DH_anon)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
if (agreementCredentials != null)
{
// TODO[tls-ops] Where to check that the domain parameters match the server's?
this.dhPeerCertificate = validatePeerCertificate(ConnectionEnd.client, clientCertificate);
}
}
public void processClientKeyExchange(InputStream input) throws IOException
{
if (dhPeerCertificate != null)
{
// For dss_fixed_dh and rsa_fixed_dh, the key arrived in the client certificate
return;
}
byte[] y = TlsUtils.readOpaque16(input);
processEphemeral(y);
}
public TlsSecret generatePreMasterSecret() throws IOException
{
if (agreementCredentials != null)
{
return agreementCredentials.generateAgreement(dhPeerCertificate);
}
if (agreement != null)
{
return agreement.calculateSecret();
}
throw new TlsFatalAlert(AlertDescription.internal_error);
}
protected void generateEphemeral(OutputStream output) throws IOException
{
byte[] y = agreement.generateEphemeral();
TlsUtils.writeOpaque16(y, output);
}
protected void processEphemeral(byte[] y) throws IOException
{
this.agreement.receivePeerValue(y);
}
protected TlsCertificate validatePeerCertificate(int connectionEnd, Certificate peerCertificate) throws IOException
{
if (peerCertificate.isEmpty())
{
throw new TlsFatalAlert(AlertDescription.bad_certificate);
}
return peerCertificate.getCertificateAt(0).useInRole(connectionEnd, keyExchange);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy