summaryrefslogtreecommitdiff
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
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.
-rw-r--r--ChangeLog-ssl-nio51
-rw-r--r--gnu/javax/crypto/RSACipherImpl.java11
-rw-r--r--gnu/javax/net/ssl/provider/CipherSuite.java22
-rw-r--r--gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java4
-rw-r--r--gnu/javax/net/ssl/provider/ClientHandshake.java106
-rw-r--r--gnu/javax/net/ssl/provider/ClientKeyExchange.java6
-rw-r--r--gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java20
-rw-r--r--gnu/javax/net/ssl/provider/EmptyExchangeKeys.java77
-rw-r--r--gnu/javax/net/ssl/provider/ExchangeKeys.java4
-rw-r--r--gnu/javax/net/ssl/provider/SSLContextImpl.java2
-rw-r--r--gnu/javax/net/ssl/provider/SSLEngineImpl.java2
-rw-r--r--gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java9
-rw-r--r--gnu/javax/net/ssl/provider/ServerDHParams.java3
-rw-r--r--gnu/javax/net/ssl/provider/ServerHandshake.java155
-rw-r--r--gnu/javax/net/ssl/provider/ServerKeyExchange.java9
15 files changed, 369 insertions, 112 deletions
diff --git a/ChangeLog-ssl-nio b/ChangeLog-ssl-nio
index 771cc0d02..f15d93cac 100644
--- a/ChangeLog-ssl-nio
+++ b/ChangeLog-ssl-nio
@@ -1,3 +1,54 @@
+2006-07-18 Casey Marshall <csm@gnu.org>
+
+ * 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.
+
2006-07-14 Casey Marshall <csm@gnu.org>
* gnu/java/net/protocol/http/HTTPConnection.java (getSocket):
diff --git a/gnu/javax/crypto/RSACipherImpl.java b/gnu/javax/crypto/RSACipherImpl.java
index 05f77213e..c6235c928 100644
--- a/gnu/javax/crypto/RSACipherImpl.java
+++ b/gnu/javax/crypto/RSACipherImpl.java
@@ -204,8 +204,6 @@ public class RSACipherImpl extends CipherSpi
engineUpdate (in, offset, length);
if (opmode == Cipher.DECRYPT_MODE)
{
- if (pos < dataBuffer.length)
- throw new IllegalBlockSizeException ("expecting exactly " + dataBuffer.length + " bytes");
BigInteger enc = new BigInteger (1, dataBuffer);
byte[] dec = rsaDecrypt (enc);
logger.log (Component.CRYPTO, "RSA: decryption produced\n{0}",
@@ -292,6 +290,13 @@ public class RSACipherImpl extends CipherSpi
dec = dec.multiply (r.modInverse (n)).mod (n);
}
- return dec.toByteArray ();
+ byte[] decb = dec.toByteArray();
+ if (decb[0] != 0x00)
+ {
+ byte[] b = new byte[decb.length + 1];
+ System.arraycopy(decb, 0, b, 1, decb.length);
+ decb = b;
+ }
+ return decb;
}
}
diff --git a/gnu/javax/net/ssl/provider/CipherSuite.java b/gnu/javax/net/ssl/provider/CipherSuite.java
index ee02e8281..f9701bdc7 100644
--- a/gnu/javax/net/ssl/provider/CipherSuite.java
+++ b/gnu/javax/net/ssl/provider/CipherSuite.java
@@ -492,6 +492,7 @@ public final class CipherSuite implements Constructed
private final int keyLength;
private final byte[] id;
private final String name;
+ private final boolean isResolved;
// Constructors.
// -------------------------------------------------------------------------
@@ -535,6 +536,7 @@ public final class CipherSuite implements Constructed
{
tlsSuiteNames.add(name);
}
+ isResolved = true;
}
private CipherSuite(byte[] id)
@@ -549,6 +551,7 @@ public final class CipherSuite implements Constructed
keyLength = 0;
this.id = id;
name = null;
+ isResolved = false;
}
// Class methods.
@@ -688,7 +691,7 @@ public final class CipherSuite implements Constructed
public CipherSuite resolve()
{
- if (id[0] == 0x00) switch (id[1])
+ if (id[0] == 0x00) switch (id[1] & 0xFF)
{
case 0x00: return TLS_NULL_WITH_NULL_NULL;
case 0x01: return TLS_RSA_WITH_NULL_MD5;
@@ -745,9 +748,26 @@ public final class CipherSuite implements Constructed
case 0x7C: return TLS_RSA_WITH_3DES_EDE_CBC_RMD;
case 0x7D: return TLS_RSA_WITH_AES_128_CBC_RMD;
case 0x7E: return TLS_RSA_WITH_AES_256_CBC_RMD;*/
+ case 0x8A: return TLS_PSK_WITH_RC4_128_SHA;
+ case 0x8B: return TLS_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x8C: return TLS_PSK_WITH_AES_128_CBC_SHA;
+ case 0x8D: return TLS_PSK_WITH_AES_256_CBC_SHA;
+ case 0x8E: return TLS_DHE_PSK_WITH_RC4_128_SHA;
+ case 0x8F: return TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x90: return TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
+ case 0x91: return TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
+ case 0x92: return TLS_RSA_PSK_WITH_RC4_128_SHA;
+ case 0x93: return TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x94: return TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
+ case 0x95: return TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
}
return this;
}
+
+ public boolean isResolved()
+ {
+ return isResolved;
+ }
public int keyLength()
{
diff --git a/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java b/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
index a40f77ba2..e63e03c0a 100644
--- a/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
+++ b/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
@@ -106,8 +106,8 @@ public class ClientDHE_PSKParameters extends ExchangeKeys implements Builder, Co
public ClientDiffieHellmanPublic params()
{
- return new ClientDiffieHellmanPublic((ByteBuffer) buffer.duplicate()
- .position(identityLength()).limit(length()));
+ return new ClientDiffieHellmanPublic(((ByteBuffer) buffer.duplicate()
+ .position(identityLength()).limit(length())).slice());
}
/* (non-Javadoc)
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()
diff --git a/gnu/javax/net/ssl/provider/ClientKeyExchange.java b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
index cc05ff736..2006e7385 100644
--- a/gnu/javax/net/ssl/provider/ClientKeyExchange.java
+++ b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
@@ -95,8 +95,10 @@ public class ClientKeyExchange implements Handshake.Body
else if (alg == KeyExchangeAlgorithm.PSK)
return new ClientPSKParameters(buffer.duplicate());
else if (alg == KeyExchangeAlgorithm.RSA_PSK)
- return new ClientRSA_PSKParameters(buffer.duplicate(), version);
- throw new IllegalArgumentException("unsupported key exchange");
+ return new ClientRSA_PSKParameters(buffer.duplicate());
+ else if (alg == KeyExchangeAlgorithm.NONE)
+ return new EmptyExchangeKeys();
+ throw new IllegalArgumentException("unsupported key exchange: " + alg);
}
public int length()
diff --git a/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java b/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
index 3023ff9a2..f7483a94c 100644
--- a/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
+++ b/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.ByteBuffer;
@@ -49,26 +52,21 @@ import java.nio.charset.Charset;
*/
public class ClientRSA_PSKParameters extends ExchangeKeys implements Builder, Constructed
{
- private final ProtocolVersion version;
-
- public ClientRSA_PSKParameters(ByteBuffer buffer, ProtocolVersion version)
+ public ClientRSA_PSKParameters(ByteBuffer buffer)
{
super(buffer);
- this.version = version;
}
- public ClientRSA_PSKParameters(String identity, EncryptedPreMasterSecret epms,
- ProtocolVersion version)
+ public ClientRSA_PSKParameters(String identity, ByteBuffer epms)
{
super(null);
Charset utf8 = Charset.forName("UTF-8");
ByteBuffer idBuf = utf8.encode(identity);
- buffer = ByteBuffer.allocate(2 + idBuf.remaining() + epms.length());
+ buffer = ByteBuffer.allocate(2 + idBuf.remaining() + epms.remaining());
buffer.putShort((short) idBuf.remaining());
buffer.put(idBuf);
- buffer.put(epms.buffer());
+ buffer.put(epms);
buffer.rewind();
- this.version = version;
}
/* (non-Javadoc)
@@ -102,8 +100,8 @@ public class ClientRSA_PSKParameters extends ExchangeKeys implements Builder, Co
public EncryptedPreMasterSecret secret()
{
return new EncryptedPreMasterSecret
- ((ByteBuffer) buffer.duplicate().position(identityLength())
- .limit(buffer.capacity()), version);
+ (((ByteBuffer) buffer.duplicate().position(identityLength())
+ .limit(buffer.capacity())).slice(), ProtocolVersion.TLS_1);
}
/* (non-Javadoc)
diff --git a/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java b/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
new file mode 100644
index 000000000..acf4cfa03
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
@@ -0,0 +1,77 @@
+/* EmptyExchangeKeys.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class EmptyExchangeKeys
+ extends ExchangeKeys
+{
+
+ public EmptyExchangeKeys()
+ {
+ super(ByteBuffer.allocate(0));
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return 0;
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ String ret = "struct { };";
+ if (prefix != null) ret = prefix + ret;
+ return ret;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ExchangeKeys.java b/gnu/javax/net/ssl/provider/ExchangeKeys.java
index 3ee79d7d0..f161f484a 100644
--- a/gnu/javax/net/ssl/provider/ExchangeKeys.java
+++ b/gnu/javax/net/ssl/provider/ExchangeKeys.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
public abstract class ExchangeKeys implements Constructed
{
@@ -47,6 +48,7 @@ public abstract class ExchangeKeys implements Constructed
public ExchangeKeys (final ByteBuffer buffer)
{
- this.buffer = buffer;
+ if (buffer != null)
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
}
} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/SSLContextImpl.java b/gnu/javax/net/ssl/provider/SSLContextImpl.java
index 0c00ccb2a..cf7c8e4e3 100644
--- a/gnu/javax/net/ssl/provider/SSLContextImpl.java
+++ b/gnu/javax/net/ssl/provider/SSLContextImpl.java
@@ -174,7 +174,7 @@ public final class SSLContextImpl extends SSLContextSpi
if ((keyManagers[i] instanceof X509ExtendedKeyManager)
&& keyManager == null)
keyManager = (X509ExtendedKeyManager) keyManagers[i];
- if (keyManagers[i] instanceof PreSharedKeyManagerFactoryImpl
+ if (keyManagers[i] instanceof PreSharedKeyManager
&& pskManager == null)
pskManager = (PreSharedKeyManager) keyManagers[i];
}
diff --git a/gnu/javax/net/ssl/provider/SSLEngineImpl.java b/gnu/javax/net/ssl/provider/SSLEngineImpl.java
index e198c3f0e..26f02e072 100644
--- a/gnu/javax/net/ssl/provider/SSLEngineImpl.java
+++ b/gnu/javax/net/ssl/provider/SSLEngineImpl.java
@@ -104,8 +104,6 @@ public final class SSLEngineImpl extends SSLEngine
SSLEngineImpl (SSLContextImpl contextImpl, String host, int port)
{
super(host, port);
- logger.logv(java.util.logging.Level.INFO, "creating SSLEngine {0} {1}:{2}",
- this, host, port);
this.contextImpl = contextImpl;
handlers = new SSLRecordHandler[256];
session = new SessionImpl();
diff --git a/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java b/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
index 2cc42929c..edc3ac259 100644
--- a/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
+++ b/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.ByteBuffer;
@@ -78,7 +81,7 @@ public class ServerDHE_PSKParameters implements Constructed, Builder, ServerKeyE
buffer = ByteBuffer.allocate(2 + hintBuf.remaining() + dhParams.remaining());
buffer.putShort((short) hintBuf.remaining());
buffer.put(hintBuf);
- buffer.put(buffer);
+ buffer.put(dhParams);
}
public KeyExchangeAlgorithm algorithm()
@@ -108,8 +111,8 @@ public class ServerDHE_PSKParameters implements Constructed, Builder, ServerKeyE
public ServerDHParams params()
{
- return new ServerDHParams((ByteBuffer) buffer.duplicate().position
- (hintLength()).limit(buffer.capacity()));
+ return new ServerDHParams(((ByteBuffer) buffer.duplicate().position
+ (hintLength()).limit(buffer.capacity())).slice());
}
/* (non-Javadoc)
diff --git a/gnu/javax/net/ssl/provider/ServerDHParams.java b/gnu/javax/net/ssl/provider/ServerDHParams.java
index 38abe93bb..55d4a41da 100644
--- a/gnu/javax/net/ssl/provider/ServerDHParams.java
+++ b/gnu/javax/net/ssl/provider/ServerDHParams.java
@@ -42,6 +42,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
/**
* The server's Diffie-Hellman parameters message.
@@ -61,7 +62,7 @@ public class ServerDHParams implements Builder, ServerKeyExchangeParams
public ServerDHParams (final ByteBuffer buffer)
{
- this.buffer = buffer;
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
}
public ServerDHParams (final BigInteger p, final BigInteger g,
diff --git a/gnu/javax/net/ssl/provider/ServerHandshake.java b/gnu/javax/net/ssl/provider/ServerHandshake.java
index 0d77bda04..300012a4b 100644
--- a/gnu/javax/net/ssl/provider/ServerHandshake.java
+++ b/gnu/javax/net/ssl/provider/ServerHandshake.java
@@ -70,6 +70,8 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@@ -140,6 +142,7 @@ class ServerHandshake extends AbstractHandshake
private X509Certificate localCert = null;
private boolean helloV2 = false;
private KeyPair dhPair;
+ private PrivateKey serverKey;
// Delegated tasks we use.
private GenDH genDH;
@@ -198,6 +201,7 @@ class ServerHandshake extends AbstractHandshake
// Figure out which SignatureAlgorithms we can support.
HashSet<KeyExchangeAlgorithm> kexes = new HashSet<KeyExchangeAlgorithm>(8);
+ kexes.add(NONE);
X509ExtendedKeyManager km = engine.contextImpl.keyManager;
if (km != null)
{
@@ -233,15 +237,20 @@ class ServerHandshake extends AbstractHandshake
continue;
if (!kexes.contains(suite.keyExchangeAlgorithm()))
continue;
- suites.add (suite);
+ suites.add(suite);
}
for (CipherSuite suite : clientSuites)
{
- if (suites.contains (suite))
- return suite.resolve();
+ CipherSuite resolved = suite.resolve();
+ if (!resolved.isResolved())
+ continue;
+ if (suites.contains(resolved))
+ return resolved;
}
- throw new AlertException (new Alert (Alert.Level.FATAL,
- Alert.Description.INSUFFICIENT_SECURITY));
+
+ // We didn't find a match?
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.INSUFFICIENT_SECURITY));
}
/**
@@ -496,44 +505,7 @@ class ServerHandshake extends AbstractHandshake
{
ClientPSKParameters params = (ClientPSKParameters)
kex.exchangeKeys();
- SecretKey key = null;
- try
- {
- key = engine.contextImpl.pskManager.getKey(params.identity());
- }
- catch (KeyManagementException kme)
- {
- // Ignore; we hide the fact that a PSK identity was
- // not found.
- }
- if (key != null)
- {
- byte[] keyb = key.getEncoded();
- preMasterSecret = new byte[(2 * keyb.length) + 4];
- preMasterSecret[0] = (byte) (keyb.length >>> 8);
- preMasterSecret[1] = (byte) keyb.length;
- preMasterSecret[keyb.length + 2]
- = (byte) (keyb.length >>> 8);
- preMasterSecret[keyb.length + 3]
- = (byte) keyb.length;
- System.arraycopy(keyb, 0, preMasterSecret,
- keyb.length + 4, keyb.length);
- }
- else
- {
- // Generate a random, fake secret.
- preMasterSecret = new byte[8];
- preMasterSecret[1] = 2;
- preMasterSecret[5] = 2;
- preMasterSecret[6] = (byte) engine.session().random().nextInt();
- preMasterSecret[7] = (byte) engine.session().random().nextInt();
- }
-
- generateMasterSecret(clientRandom, serverRandom,
- engine.session());
- byte[][] keys = generateKeys(clientRandom, serverRandom,
- engine.session());
- setupSecurityParameters(keys, false, engine, compression);
+ generatePSKSecret(params.identity(), null, false);
}
break;
@@ -554,12 +526,6 @@ class ServerHandshake extends AbstractHandshake
catch (KeyManagementException kme)
{
}
- if (psk == null)
- {
- byte[] fakeKey = new byte[16];
- engine.session().random().nextBytes(fakeKey);
- psk = new SecretKeySpec(fakeKey, "DHE_PSK");
- }
keyExchangeTask = new DHE_PSKGen(clientKey, psk, false);
tasks.add(keyExchangeTask);
}
@@ -588,6 +554,25 @@ class ServerHandshake extends AbstractHandshake
tasks.add(keyExchangeTask);
}
break;
+
+ case 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];
+ }
+ break;
}
// XXX SRP
@@ -863,6 +848,7 @@ output_loop:
outBuffer.position(outBuffer.position() + l);
CipherSuite cs = engine.session().suite;
+ KeyExchangeAlgorithm kex = cs.keyExchangeAlgorithm();
if (continuedSession)
{
byte[][] keys = generateKeys(clientRandom, serverRandom,
@@ -871,27 +857,24 @@ output_loop:
engine.changeCipherSpec();
state = WRITE_FINISHED;
}
- else if (cs.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS
- || cs.keyExchangeAlgorithm() == RSA_PSK)
+ else if (kex == DHE_DSS || kex == DHE_RSA || kex == RSA
+ || kex == RSA_PSK)
{
certLoader = new CertLoader();
tasks.add(certLoader);
state = WRITE_CERTIFICATE;
- if (cs.keyExchangeAlgorithm() == DHE_DSS
- || cs.keyExchangeAlgorithm() == DHE_RSA)
+ if (kex == DHE_DSS || kex == DHE_RSA)
{
genDH = new GenDH();
tasks.add(genDH);
- state = WRITE_SERVER_KEY_EXCHANGE;
}
break output_loop;
}
- else if (engine.session().suite.keyExchangeAlgorithm() == PSK)
+ else if (kex == PSK)
{
state = WRITE_SERVER_KEY_EXCHANGE;
}
- else if (cs.keyExchangeAlgorithm() == DHE_PSK
- || cs.keyExchangeAlgorithm() == DH_anon)
+ else if (kex == DHE_PSK || kex == DH_anon)
{
genDH = new GenDH();
tasks.add(genDH);
@@ -957,6 +940,8 @@ output_loop:
state = WRITE_SERVER_KEY_EXCHANGE;
break output_loop;
}
+ else if (kexalg == RSA_PSK)
+ state = WRITE_SERVER_KEY_EXCHANGE;
else if (engine.getWantClientAuth() || engine.getNeedClientAuth())
{
state = WRITE_CERTIFICATE_REQUEST;
@@ -1003,23 +988,47 @@ output_loop:
paramBuffer = psk.buffer();
}
}
+ if (kex == RSA_PSK)
+ {
+ String idHint = engine.contextImpl.pskManager.chooseIdentityHint();
+ if (idHint != null)
+ {
+ ServerRSA_PSKParameters params
+ = new ServerRSA_PSKParameters(idHint);
+ paramBuffer = params.buffer();
+ }
+ }
+ if (kex == PSK)
+ {
+ String idHint = engine.contextImpl.pskManager.chooseIdentityHint();
+ if (idHint != null)
+ {
+ ServerPSKParameters params
+ = new ServerPSKParameters(idHint);
+ paramBuffer = params.buffer();
+ }
+ }
// XXX handle SRP
- ServerKeyExchangeBuilder ske
- = new ServerKeyExchangeBuilder(engine.session().suite);
- ske.setParams(paramBuffer);
- if (sigBuffer != null)
- ske.setSignature(sigBuffer);
+ if (paramBuffer != null)
+ {
+ ServerKeyExchangeBuilder ske
+ = new ServerKeyExchangeBuilder(engine.session().suite);
+ ske.setParams(paramBuffer);
+ if (sigBuffer != null)
+ ske.setSignature(sigBuffer);
- if (Debug.DEBUG)
- logger.log(Component.SSL_HANDSHAKE, "{0}", ske);
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0}", ske);
- outBuffer = ske.buffer();
- int l = Math.min(fragment.remaining(), outBuffer.remaining());
- fragment.putInt((SERVER_KEY_EXCHANGE.getValue() << 24)
- | (ske.length() & 0xFFFFFF));
- fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
- outBuffer.position(outBuffer.position() + l);
+ outBuffer = ske.buffer();
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.putInt((SERVER_KEY_EXCHANGE.getValue() << 24)
+ | (ske.length() & 0xFFFFFF));
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit
+ (outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+ }
if (engine.getWantClientAuth() || engine.getNeedClientAuth())
state = WRITE_CERTIFICATE_REQUEST;
@@ -1162,6 +1171,9 @@ output_loop:
{
if (continuedSession) // No key exchange needed.
return;
+ KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
+ if (kex == NONE || kex == PSK || kex == RSA_PSK) // Don't need one.
+ return;
if (keyExchangeTask == null) // An error if we never created one.
throw new AlertException(new Alert(Alert.Level.FATAL,
Alert.Description.INTERNAL_ERROR));
@@ -1261,6 +1273,7 @@ output_loop:
X509Certificate[] chain = km.getCertificateChain(keyAlias);
engine.session().setLocalCertificates(chain);
localCert = chain[0];
+ serverKey = km.getPrivateKey(keyAlias);
if (kexalg == DH_DSS || kexalg == DH_RSA)
dhPair = new KeyPair(localCert.getPublicKey(),
km.getPrivateKey(keyAlias));
@@ -1318,6 +1331,7 @@ output_loop:
NoSuchAlgorithmException, NoSuchPaddingException, SSLException
{
Cipher rsa = Cipher.getInstance("RSA");
+ rsa.init(Cipher.DECRYPT_MODE, serverKey);
rsa.init(Cipher.DECRYPT_MODE, localCert);
preMasterSecret = rsa.doFinal(encryptedPreMasterSecret);
generateMasterSecret(clientRandom, serverRandom, engine.session());
@@ -1342,6 +1356,7 @@ output_loop:
NoSuchAlgorithmException, NoSuchPaddingException, SSLException
{
Cipher rsa = Cipher.getInstance("RSA");
+ rsa.init(Cipher.DECRYPT_MODE, serverKey);
rsa.init(Cipher.DECRYPT_MODE, localCert);
byte[] rsaSecret = rsa.doFinal(encryptedPreMasterSecret);
byte[] psSecret = psKey.getEncoded();
diff --git a/gnu/javax/net/ssl/provider/ServerKeyExchange.java b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
index 6c5a72000..1206ae6b2 100644
--- a/gnu/javax/net/ssl/provider/ServerKeyExchange.java
+++ b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
@@ -82,7 +82,14 @@ public class ServerKeyExchange implements Handshake.Body
{
if (suite.keyExchangeAlgorithm ().equals (KeyExchangeAlgorithm.NONE))
return 0;
- return params().length() + signature().length();
+ int len = 0;
+ ServerKeyExchangeParams params = params();
+ Signature sig = signature();
+ if (params != null)
+ len += params.length();
+ if (sig != null)
+ len += sig.length();
+ return len;
}
/**