summaryrefslogtreecommitdiff
path: root/gnu/javax/net/ssl/provider/ClientHandshake.java
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-07-18 08:12:30 +0000
committerCasey Marshall <csm@gnu.org>2006-07-18 08:12:30 +0000
commitceca0e3930ab18748f1b02be3a6260c3daf4734f (patch)
treeb13267f576e6612195406324e0f6b97086b17896 /gnu/javax/net/ssl/provider/ClientHandshake.java
parent6ce231a4863bc4073ddc7eaa36429f08a8dd7a53 (diff)
downloadclasspath-ssl-nio-branch.tar.gz
2006-07-18 Casey Marshall <csm@gnu.org>ssl-nio-branch
* gnu/javax/net/ssl/provider/ClientHandshake.java (implHandleInput, implHandleOutput): fix PSK exchange handling. (ClientDHGen.full): new field. (ClientDHGen.implRun): run full key exchange if `full' is true. (ClientDHGen.serverKey): new method. (RSAGen.full): new field. (RSAGen.implRun): run full key exchange if `full' is true. * gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java (params): slice the buffer. * gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java (<init>): use `dhParams,' not `buffer.' (params): slice the buffer. * gnu/javax/net/ssl/provider/ServerKeyExchange.java (length): handle case where parameters or signature are null. * gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java (version): removed. (<init>): don't take version argument. (<init>): don't take version argument; take buffer argument. (secret): pass TLS_1 to EncryptedPreMasterSecret constructor. * gnu/javax/net/ssl/provider/CipherSuite.java (isResolved): new field. (<init>, <init>): set `isResolved.' (resolve): add PSK cipher suite detection. (isResolved): new method. * gnu/javax/net/ssl/provider/ServerHandshake.java (serverKey): new field. (chooseSuites): choose NONE key exchanges, too; omit unresolved cipher suites. (implHandleInput, implHandleOutput): fix PSK handling. (checkKeyExchange): update for NONE and PSK exchanges. (CertLoader.implRun): grab our private key here. (RSAKeyExchange.implRun): initialize RSA cipher with our private key. (RSA_PSKExchange.implRun): likewise. * gnu/javax/net/ssl/provider/ExchangeKeys.java (<init>): duplicate and order the buffer; handle null argument. * gnu/javax/net/ssl/provider/ClientKeyExchange.java (exchangeKeys): handle NONE exchange. * gnu/javax/net/ssl/provider/SSLContextImpl.java (engineInit): handle PSK key managers properly. * gnu/javax/net/ssl/provider/SSLEngineImpl.java (<init>): remove debug logging. * gnu/javax/net/ssl/provider/ServerDHParams.java (<init>): duplicate and order the buffer. * gnu/javax/crypto/RSACipherImpl.java (doFinal): allow short input. (rsaDecrypt): ensure there's a leading zero. * gnu/javax/net/ssl/provider/EmptyExchangeKeys.java: new file.
Diffstat (limited to 'gnu/javax/net/ssl/provider/ClientHandshake.java')
-rw-r--r--gnu/javax/net/ssl/provider/ClientHandshake.java106
1 files changed, 92 insertions, 14 deletions
diff --git a/gnu/javax/net/ssl/provider/ClientHandshake.java b/gnu/javax/net/ssl/provider/ClientHandshake.java
index 494e66dc7..123137d49 100644
--- a/gnu/javax/net/ssl/provider/ClientHandshake.java
+++ b/gnu/javax/net/ssl/provider/ClientHandshake.java
@@ -56,6 +56,7 @@ import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
@@ -69,11 +70,14 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
@@ -223,6 +227,7 @@ public class ClientHandshake extends AbstractHandshake
}
}
+ KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
if (continuedSession)
{
byte[][] keys = generateKeys(clientRandom, serverRandom,
@@ -230,8 +235,13 @@ public class ClientHandshake extends AbstractHandshake
setupSecurityParameters(keys, true, engine, compression);
state = READ_FINISHED;
}
- else
+ else if (kex == RSA || kex == DH_DSS || kex == DH_RSA
+ || kex == DHE_DSS || kex == DHE_RSA || kex == RSA_PSK)
state = READ_CERTIFICATE;
+ else if (kex == DH_anon || kex == PSK || kex == DHE_PSK)
+ state = READ_SERVER_KEY_EXCHANGE;
+ else
+ state = READ_CERTIFICATE_REQUEST;
}
break;
@@ -269,12 +279,15 @@ public class ClientHandshake extends AbstractHandshake
tasks.add(certVerifier);
// If we are doing an RSA key exchange, generate our parameters.
- if (engine.session().suite.keyExchangeAlgorithm()
- == KeyExchangeAlgorithm.RSA)
+ KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
+ if (kea == RSA || kea == RSA_PSK)
{
- keyExchange = new RSAGen();
+ keyExchange = new RSAGen(kea == RSA);
tasks.add(keyExchange);
- state = READ_CERTIFICATE_REQUEST;
+ if (kea == RSA)
+ state = READ_CERTIFICATE_REQUEST;
+ else
+ state = READ_SERVER_KEY_EXCHANGE;
}
else
state = READ_SERVER_KEY_EXCHANGE;
@@ -291,6 +304,15 @@ public class ClientHandshake extends AbstractHandshake
&& kexalg != DHE_PSK && kexalg != PSK && kexalg != RSA_PSK)
throw new AlertException(new Alert(Level.FATAL,
Description.UNEXPECTED_MESSAGE));
+
+ if (handshake.type() != Handshake.Type.SERVER_KEY_EXCHANGE)
+ {
+ if (kexalg != RSA_PSK && kexalg != PSK)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+ state = READ_CERTIFICATE_REQUEST;
+ return HandshakeStatus.NEED_UNWRAP;
+ }
ServerKeyExchange skex = (ServerKeyExchange) handshake.body();
ByteBuffer paramsBuffer = null;
@@ -318,7 +340,21 @@ public class ClientHandshake extends AbstractHandshake
dhParams.y());
DHParameterSpec params = new DHParameterSpec(dhParams.p(),
dhParams.g());
- keyExchange = new ClientDHGen(serverKey, params);
+ keyExchange = new ClientDHGen(serverKey, params, true);
+ tasks.add(keyExchange);
+ }
+ if (kexalg == DHE_PSK)
+ {
+ ServerDHE_PSKParameters pskParams = (ServerDHE_PSKParameters)
+ skex.params();
+ ServerDHParams dhParams = pskParams.params();
+ DHPublicKey serverKey = new GnuDHPublicKey(null,
+ dhParams.p(),
+ dhParams.g(),
+ dhParams.y());
+ DHParameterSpec params = new DHParameterSpec(dhParams.p(),
+ dhParams.g());
+ keyExchange = new ClientDHGen(serverKey, params, false);
tasks.add(keyExchange);
}
state = READ_CERTIFICATE_REQUEST;
@@ -616,13 +652,14 @@ outer_loop:
+ " set the security property"
+ " \"jessie.client.psk.identity\"");
ClientRSA_PSKParameters params =
- new ClientRSA_PSKParameters(identity, epms,
- engine.session().version);
+ new ClientRSA_PSKParameters(identity, epms.buffer());
ckex.setExchangeKeys(params.buffer());
+ generatePSKSecret(identity, preMasterSecret, true);
}
}
if (kea == DHE_PSK)
{
+ assert(keyExchange instanceof ClientDHGen);
assert(dhPair != null);
String identity = getPSKIdentity();
if (identity == null)
@@ -634,6 +671,7 @@ outer_loop:
new ClientDHE_PSKParameters(identity,
new ClientDiffieHellmanPublic(pubkey.getY()));
ckex.setExchangeKeys(params.buffer());
+ generatePSKSecret(identity, preMasterSecret, true);
}
if (kea == PSK)
{
@@ -642,9 +680,27 @@ outer_loop:
throw new SSLException("no pre-shared key identity; set"
+ " the security property"
+ " \"jessie.client.psk.identity\"");
+ generatePSKSecret(identity, null, true);
ClientPSKParameters params = new ClientPSKParameters(identity);
ckex.setExchangeKeys(params.buffer());
}
+ if (kea == NONE)
+ {
+ Inflater inflater = null;
+ Deflater deflater = null;
+ if (compression == CompressionMethod.ZLIB)
+ {
+ inflater = new Inflater();
+ deflater = new Deflater();
+ }
+ inParams = new InputSecurityParameters(null, null, inflater,
+ engine.session(),
+ engine.session().suite);
+ outParams = new OutputSecurityParameters(null, null, deflater,
+ engine.session(),
+ engine.session().suite);
+ engine.session().privateData.masterSecret = new byte[0];
+ }
if (Debug.DEBUG)
logger.logv(Component.SSL_HANDSHAKE, "{0}", ckex);
@@ -894,11 +950,13 @@ outer_loop:
{
private final DHPublicKey serverKey;
private final DHParameterSpec params;
+ private final boolean full;
- ClientDHGen(DHPublicKey serverKey, DHParameterSpec params)
+ ClientDHGen(DHPublicKey serverKey, DHParameterSpec params, boolean full)
{
this.serverKey = serverKey;
this.params = params;
+ this.full = full;
}
public void implRun()
@@ -930,13 +988,19 @@ outer_loop:
"client keys public:{0} private:{1}", dhPair.getPublic(),
dhPair.getPrivate());
- // We have enough info to do the full key exchange; so let's do it.
initDiffieHellman((DHPrivateKey) dhPair.getPrivate(), engine.session().random());
- DHPhase phase = new DHPhase(serverKey);
+
+ // We have enough info to do the full key exchange; so let's do it.
+ DHPhase phase = new DHPhase(serverKey, full);
phase.run();
if (phase.thrown() != null)
throw new SSLException(phase.thrown());
}
+
+ DHPublicKey serverKey()
+ {
+ return serverKey;
+ }
}
class CertLoader extends DelegatedTask
@@ -966,6 +1030,17 @@ outer_loop:
class RSAGen extends DelegatedTask
{
private byte[] encryptedPreMasterSecret;
+ private final boolean full;
+
+ RSAGen()
+ {
+ this(true);
+ }
+
+ RSAGen(boolean full)
+ {
+ this.full = full;
+ }
public void implRun()
throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
@@ -998,9 +1073,12 @@ outer_loop:
encryptedPreMasterSecret = rsa.doFinal(preMasterSecret);
// Generate our session keys, because we can.
- generateMasterSecret(clientRandom, serverRandom, engine.session());
- byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
- setupSecurityParameters(keys, true, engine, compression);
+ if (full)
+ {
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, true, engine, compression);
+ }
}
byte[] encryptedSecret()