This fixes some bugs in Jessie found through testing the implementation against itself (Mauve tests, which I'll add there at some point).

I'm planning to merge the Jessie code back to the generics branch sometime after the next release is made. It seems complete and stable enough that it is sufficient to replace the existing implementation. SRP is still not yet reimplemented, but this isn't that big a deal, since I don't think it is widely used, and the spec is still only a draft at this point.

Thanks.

2006-07-18  Casey Marshall  <[EMAIL PROTECTED]>

        * 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.

### Eclipse Workspace Patch 1.0
#P classpath-ssl-nio
Index: gnu/javax/net/ssl/provider/ClientHandshake.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ClientHandshake.java,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 ClientHandshake.java
--- gnu/javax/net/ssl/provider/ClientHandshake.java     15 Jul 2006 00:51:02 
-0000      1.1.2.2
+++ gnu/javax/net/ssl/provider/ClientHandshake.java     18 Jul 2006 07:59:42 
-0000
@@ -56,6 +56,7 @@
 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.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 @@
                 }
             }
 
+          KeyExchangeAlgorithm kex = 
engine.session().suite.keyExchangeAlgorithm();
           if (continuedSession)
             {
               byte[][] keys = generateKeys(clientRandom, serverRandom,
@@ -230,8 +235,13 @@
               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 @@
           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 @@
               && 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 @@
                                                          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 @@
                                                + " 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 @@
                     new ClientDHE_PSKParameters(identity,
                                                 new 
ClientDiffieHellmanPublic(pubkey.getY()));
                   ckex.setExchangeKeys(params.buffer());
+                  generatePSKSecret(identity, preMasterSecret, true);
                 }
               if (kea == PSK)
                 {
@@ -642,9 +680,27 @@
                     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 @@
   {
     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 @@
                     "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 @@
   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 @@
       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()
Index: gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ClientDHE_PSKParameters.java,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 ClientDHE_PSKParameters.java
--- gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java     15 Jul 2006 
00:51:02 -0000      1.1.2.1
+++ gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java     18 Jul 2006 
07:59:39 -0000
@@ -106,8 +106,8 @@
 
   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)
Index: gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ServerDHE_PSKParameters.java,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 ServerDHE_PSKParameters.java
--- gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java     15 Jul 2006 
00:51:02 -0000      1.1.2.1
+++ gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java     18 Jul 2006 
07:59:46 -0000
@@ -38,6 +38,9 @@
 
 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 @@
     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 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)
Index: gnu/javax/net/ssl/provider/ServerKeyExchange.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/ServerKeyExchange.java,v
retrieving revision 1.1.4.1.2.3
diff -u -r1.1.4.1.2.3 ServerKeyExchange.java
--- gnu/javax/net/ssl/provider/ServerKeyExchange.java   15 Jul 2006 00:51:02 
-0000      1.1.4.1.2.3
+++ gnu/javax/net/ssl/provider/ServerKeyExchange.java   18 Jul 2006 07:59:54 
-0000
@@ -82,7 +82,14 @@
   {
     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;
   }
 
   /**
Index: gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ClientRSA_PSKParameters.java,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 ClientRSA_PSKParameters.java
--- gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java     15 Jul 2006 
00:51:02 -0000      1.1.2.1
+++ gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java     18 Jul 2006 
07:59:43 -0000
@@ -38,6 +38,9 @@
 
 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 @@
  */
 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 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)
Index: gnu/javax/net/ssl/provider/CipherSuite.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/CipherSuite.java,v
retrieving revision 1.1.4.1.2.4
diff -u -r1.1.4.1.2.4 CipherSuite.java
--- gnu/javax/net/ssl/provider/CipherSuite.java 15 Jul 2006 00:51:02 -0000      
1.1.4.1.2.4
+++ gnu/javax/net/ssl/provider/CipherSuite.java 18 Jul 2006 07:59:39 -0000
@@ -492,6 +492,7 @@
   private final int keyLength;
   private final byte[] id;
   private final String name;
+  private final boolean isResolved;
 
   // Constructors.
   // -------------------------------------------------------------------------
@@ -535,6 +536,7 @@
       {
         tlsSuiteNames.add(name);
       }
+    isResolved = true;
   }
 
   private CipherSuite(byte[] id)
@@ -549,6 +551,7 @@
     keyLength = 0;
     this.id = id;
     name = null;
+    isResolved = false;
   }
 
   // Class methods.
@@ -688,7 +691,7 @@
   
   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 @@
       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()
   {
Index: gnu/javax/net/ssl/provider/ServerHandshake.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ServerHandshake.java,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 ServerHandshake.java
--- gnu/javax/net/ssl/provider/ServerHandshake.java     15 Jul 2006 00:51:02 
-0000      1.1.2.6
+++ gnu/javax/net/ssl/provider/ServerHandshake.java     18 Jul 2006 07:59:54 
-0000
@@ -70,6 +70,8 @@
 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 @@
   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 @@
     // 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 @@
           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 @@
                   {
                     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 @@
                     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 @@
                     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 @@
               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 @@
                   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 @@
                   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 @@
                       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 @@
   {
     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 @@
       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 @@
              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 @@
              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();
Index: gnu/javax/net/ssl/provider/ExchangeKeys.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ExchangeKeys.java,v
retrieving revision 1.1.4.2
diff -u -r1.1.4.2 ExchangeKeys.java
--- gnu/javax/net/ssl/provider/ExchangeKeys.java        12 Jul 2006 19:11:02 
-0000      1.1.4.2
+++ gnu/javax/net/ssl/provider/ExchangeKeys.java        18 Jul 2006 07:59:43 
-0000
@@ -39,6 +39,7 @@
 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 ExchangeKeys (final ByteBuffer buffer)
   {
-    this.buffer = buffer;
+    if (buffer != null)
+      this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
   }
 }
\ No newline at end of file
Index: gnu/javax/net/ssl/provider/ClientKeyExchange.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/ClientKeyExchange.java,v
retrieving revision 1.1.4.1.2.4
diff -u -r1.1.4.1.2.4 ClientKeyExchange.java
--- gnu/javax/net/ssl/provider/ClientKeyExchange.java   15 Jul 2006 00:51:02 
-0000      1.1.4.1.2.4
+++ gnu/javax/net/ssl/provider/ClientKeyExchange.java   18 Jul 2006 07:59:42 
-0000
@@ -95,8 +95,10 @@
     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()
Index: gnu/javax/net/ssl/provider/SSLContextImpl.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/SSLContextImpl.java,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 SSLContextImpl.java
--- gnu/javax/net/ssl/provider/SSLContextImpl.java      15 Jul 2006 00:51:02 
-0000      1.1.2.4
+++ gnu/javax/net/ssl/provider/SSLContextImpl.java      18 Jul 2006 07:59:44 
-0000
@@ -174,7 +174,7 @@
             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];
           }
Index: gnu/javax/net/ssl/provider/SSLEngineImpl.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/SSLEngineImpl.java,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 SSLEngineImpl.java
--- gnu/javax/net/ssl/provider/SSLEngineImpl.java       15 Jul 2006 00:51:02 
-0000      1.1.2.5
+++ gnu/javax/net/ssl/provider/SSLEngineImpl.java       18 Jul 2006 07:59:46 
-0000
@@ -104,8 +104,6 @@
   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();
Index: gnu/javax/net/ssl/provider/ServerDHParams.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/javax/net/ssl/provider/Attic/ServerDHParams.java,v
retrieving revision 1.1.4.4
diff -u -r1.1.4.4 ServerDHParams.java
--- gnu/javax/net/ssl/provider/ServerDHParams.java      15 Jul 2006 00:51:02 
-0000      1.1.4.4
+++ gnu/javax/net/ssl/provider/ServerDHParams.java      18 Jul 2006 07:59:47 
-0000
@@ -42,6 +42,7 @@
 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 ServerDHParams (final ByteBuffer buffer)
   {
-    this.buffer = buffer;
+    this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
   }
   
   public ServerDHParams (final BigInteger p, final BigInteger g,
Index: gnu/javax/crypto/RSACipherImpl.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/javax/crypto/RSACipherImpl.java,v
retrieving revision 1.1.2.2.2.1
diff -u -r1.1.2.2.2.1 RSACipherImpl.java
--- gnu/javax/crypto/RSACipherImpl.java 15 Jul 2006 00:51:03 -0000      
1.1.2.2.2.1
+++ gnu/javax/crypto/RSACipherImpl.java 18 Jul 2006 07:59:38 -0000
@@ -204,8 +204,6 @@
     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 @@
         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;
   }
 }
Index: gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
===================================================================
RCS file: gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
diff -N gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gnu/javax/net/ssl/provider/EmptyExchangeKeys.java   1 Jan 1970 00:00:00 
-0000
@@ -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 ([EMAIL PROTECTED])
+ */
+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;
+  }
+}

Attachment: PGP.sig
Description: This is a digitally signed message part

Reply via email to