org.bouncycastle.tls.TlsECDHEKeyExchange Maven / Gradle / Ivy
package org.bouncycastle.tls;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import org.bouncycastle.tls.crypto.TlsECConfig;
import org.bouncycastle.tls.crypto.TlsVerifier;
import org.bouncycastle.util.io.TeeInputStream;
/**
* (D)TLS ECDHE key exchange (see RFC 4492).
*/
public class TlsECDHEKeyExchange
extends TlsECDHKeyExchange
{
private static int checkKeyExchange(int keyExchange)
{
switch (keyExchange)
{
case KeyExchangeAlgorithm.ECDHE_ECDSA:
case KeyExchangeAlgorithm.ECDHE_RSA:
return keyExchange;
default:
throw new IllegalArgumentException("unsupported key exchange algorithm");
}
}
protected TlsCredentialedSigner serverCredentials = null;
protected TlsVerifier verifier = null;
public TlsECDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms,
TlsECConfigVerifier ecConfigVerifier, short[] clientECPointFormats, short[] serverECPointFormats)
{
super(checkKeyExchange(keyExchange), supportedSignatureAlgorithms, ecConfigVerifier, clientECPointFormats,
serverECPointFormats);
}
public TlsECDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsECConfig ecConfig,
short[] serverECPointFormats)
{
super(checkKeyExchange(keyExchange), supportedSignatureAlgorithms, ecConfig, serverECPointFormats);
}
public void processServerCredentials(TlsCredentials serverCredentials) throws IOException
{
if (!(serverCredentials instanceof TlsCredentialedSigner))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
this.serverCredentials = (TlsCredentialedSigner)serverCredentials;
}
public void processServerCertificate(Certificate serverCertificate) throws IOException
{
if (serverCertificate.isEmpty())
{
throw new TlsFatalAlert(AlertDescription.bad_certificate);
}
checkServerCertSigAlg(serverCertificate);
this.verifier = serverCertificate.getCertificateAt(0)
.createVerifier(TlsUtils.getSignatureAlgorithm(keyExchange));
}
public byte[] generateServerKeyExchange() throws IOException
{
DigestInputBuffer buf = new DigestInputBuffer();
TlsECCUtils.writeECConfig(ecConfig, buf);
this.agreement = context.getCrypto().createECDomain(ecConfig).createECDH();
generateEphemeral(buf);
DigitallySigned signedParams = TlsUtils.generateServerKeyExchangeSignature(context, serverCredentials, buf);
signedParams.encode(buf);
return buf.toByteArray();
}
public void processServerKeyExchange(InputStream input) throws IOException
{
DigestInputBuffer buf = new DigestInputBuffer();
InputStream teeIn = new TeeInputStream(input, buf);
this.ecConfig = TlsECCUtils.receiveECConfig(ecConfigVerifier, serverECPointFormats, teeIn);
byte[] point = TlsUtils.readOpaque8(teeIn);
DigitallySigned signedParams = parseSignature(input);
TlsUtils.verifyServerKeyExchangeSignature(context, verifier, buf, signedParams);
this.agreement = context.getCrypto().createECDomain(ecConfig).createECDH();
processEphemeral(clientECPointFormats, point);
}
public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
{
/*
* RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
* ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
* the use of a long-term ECDH client key would jeopardize the forward secrecy property of
* these algorithms.
*/
short[] types = certificateRequest.getCertificateTypes();
for (int i = 0; i < types.length; ++i)
{
switch (types[i])
{
case ClientCertificateType.dss_sign:
case ClientCertificateType.ecdsa_sign:
case ClientCertificateType.rsa_sign:
break;
default:
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
}
}
public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
{
if (clientCredentials instanceof TlsCredentialedSigner)
{
// OK
}
else
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
}