You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2006/07/19 00:50:14 UTC

svn commit: r423275 [3/7] - in /incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org: ./ apache/ apache/harmony/ apache/harmony/security/ apache/harmony/security/provider/ apache/harmony/security/provider/jsse/

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DataStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DataStream.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DataStream.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DataStream.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,46 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+/**
+ * This interface represents the ability of the
+ * classes to provide the chunks of data.
+ */
+public interface DataStream {
+
+    /**
+     * Checks if there is data to be read.
+     * @return true if there is the input data in the stream,
+     * false otherwise
+     */
+    public boolean hasData();
+
+    /**
+     * Retrieves the data of specified length from the stream.
+     * If the data size in the stream is less than specified length,
+     * method returns all the data contained in the stream.
+     * @return byte array containing the demanded data.
+     */
+    public byte[] getData(int length);
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DelegatedTask.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DelegatedTask.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DelegatedTask.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DelegatedTask.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,67 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * Delegated Runnable task for SSLEngine
+ */
+public class DelegatedTask implements Runnable {
+
+    private final HandshakeProtocol handshaker;
+    private final PrivilegedExceptionAction action;
+    private final AccessControlContext  context;
+    
+    /**
+     * Creates DelegatedTask
+     * @param action
+     * @param handshaker
+     * @param context
+     */
+    public DelegatedTask(PrivilegedExceptionAction action, HandshakeProtocol handshaker, AccessControlContext  context) {
+        this.action = action;
+        this.handshaker = handshaker;
+        this.context = context;
+    }
+
+    /**
+     * Executes DelegatedTask
+     */
+    public void run() {
+        synchronized (handshaker) {
+            try {
+                AccessController.doPrivileged(action, context);
+            } catch (PrivilegedActionException e) {
+                // pass exception to HandshakeProtocol
+                handshaker.delegatedTaskErr = e.getException();
+            } catch (RuntimeException e) {
+                // pass exception to HandshakeProtocol
+                handshaker.delegatedTaskErr = e;
+            }
+        }
+
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DigitalSignature.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DigitalSignature.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DigitalSignature.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DigitalSignature.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,239 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+package org.apache.harmony.security.provider.jsse;
+
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.net.ssl.SSLException;
+
+/**
+ * This class represents Signature type, as descrybed in TLS v 1.0 Protocol
+ * specification, 7.4.3. It allow to init, update and sign hash. Hash algorithm
+ * depends on SignatureAlgorithm.
+ * 
+ * select (SignatureAlgorithm)
+ *       {   case anonymous: struct { };
+ *           case rsa:
+ *               digitally-signed struct {
+ *                   opaque md5_hash[16];
+ *                   opaque sha_hash[20];
+ *               };
+ *           case dsa:
+ *               digitally-signed struct {
+ *                   opaque sha_hash[20];
+ *               };
+ *       } Signature;
+ * 
+ * Digital signing description see in TLS spec., 4.7.
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ *  
+ */
+public class DigitalSignature {
+
+    private MessageDigest md5 = null;
+    private MessageDigest sha = null;
+    private Signature signature = null;
+    private Cipher cipher = null;
+    
+    private byte[] md5_hash;
+    private byte[] sha_hash;
+     
+    /**
+     * Create Signature type
+     * @param keyExchange
+     */
+    public DigitalSignature(int keyExchange) {
+        try { 
+            if (keyExchange == CipherSuite.KeyExchange_RSA_EXPORT ||
+                    keyExchange == CipherSuite.KeyExchange_DHE_RSA ||
+                    keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
+                // SignatureAlgorithm is rsa
+                md5 = MessageDigest.getInstance("MD5");
+                sha = MessageDigest.getInstance("SHA-1");
+                cipher = Cipher.getInstance("RSA");
+            } else if (keyExchange == CipherSuite.KeyExchange_DHE_DSS ||
+                    keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT ) {
+                // SignatureAlgorithm is dsa
+                sha = MessageDigest.getInstance("SHA-1");
+                signature = Signature.getInstance("NONEwithDSA");
+// The Signature should be empty in case of anonimous signature algorithm:
+//            } else if (keyExchange == CipherSuite.KeyExchange_DH_anon ||
+//                    keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {            
+//
+            }
+        } catch (Exception e) {
+            throw new AlertException(
+                    AlertProtocol.INTERNAL_ERROR,
+                    new SSLException(
+                            "INTERNAL ERROR: Unexpected exception on digital signature",
+                            e));
+        }    
+            
+    }
+    
+    /**
+     * Initiate Signature type by private key
+     * @param key
+     */
+    public void init(PrivateKey key) {
+        try {
+            if (signature != null) {
+                signature.initSign(key);
+            } else if (cipher != null) {
+                cipher.init(Cipher.ENCRYPT_MODE, key);
+            }
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+    
+    /**
+     * Initiate Signature type by certificate
+     * @param cert
+     */
+    public void init(Certificate cert) {
+        try {
+            if (signature != null) {
+                signature.initVerify(cert);
+            } else if (cipher != null) {
+                cipher.init(Cipher.DECRYPT_MODE, cert);
+            }
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+    
+    /**
+     * Update Signature hash
+     * @param data
+     */
+    public void update(byte[] data) {
+        try {
+            if (sha != null) {
+                sha.update(data);
+            }
+            if (md5 != null) {
+                md5.update(data);
+            }
+        } catch (Exception e){
+            e.printStackTrace();
+        }        
+    }
+    
+    /**
+     * Sets MD5 hash
+     * @param data
+     */
+    public void setMD5(byte[] data) {
+        md5_hash = data;    
+    }
+    
+    /**
+     * Sets SHA hash
+     * @param data
+     */
+    public void setSHA(byte[] data) {
+        sha_hash = data;    
+    }
+    
+    /**
+     * Sign hash
+     * @return Signature bytes
+     */
+    public byte[] sign() {
+        try {
+            if (md5 != null && md5_hash == null) {
+                md5_hash = new byte[16];
+                md5.digest(md5_hash, 0, md5_hash.length);
+            }    
+            if (md5_hash != null) {
+                if (signature != null) {
+                    signature.update(md5_hash);
+                } else if (cipher != null) {
+                    cipher.update(md5_hash);
+                }
+            }
+            if (sha != null && sha_hash == null) {
+                sha_hash = new byte[20];
+                sha.digest(sha_hash, 0, sha_hash.length);
+            }
+            if (sha_hash != null) {
+                if (signature != null) {
+                    signature.update(sha_hash);
+                } else if (cipher != null) {
+                    cipher.update(sha_hash);
+                }
+            }
+            if (signature != null) {
+                return signature.sign();
+            } else if (cipher != null) {
+                return cipher.doFinal();
+            } 
+            return new byte[0];
+        } catch (Exception e){
+            e.printStackTrace();
+            return new byte[0];
+        }    
+    }
+
+    /**
+     * Verifies the signature data. 
+     * @param data - the signature bytes 
+     * @return true if verified
+     */
+    public boolean verifySignature(byte[] data) {
+        try {
+            if (signature != null) {
+                return signature.verify(data);
+            } else if (cipher != null) {
+                byte[] decrypt = cipher.doFinal(data);
+                byte[] md5_sha;
+                if (md5_hash != null && sha_hash != null) {
+                    md5_sha = new byte[md5_hash.length + sha_hash.length];
+                    System.arraycopy(md5_hash, 0, md5_sha, 0, md5_hash.length);
+                    System.arraycopy(sha_hash, 0, md5_sha, md5_hash.length, sha_hash.length);
+                } else if (md5_hash != null) {
+                    md5_sha = md5_hash;
+                } else {
+                    md5_sha = sha_hash;
+                }
+                if (Arrays.equals(decrypt, md5_sha)) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else if (data == null || data.length == 0) {
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e){
+                e.printStackTrace();
+                return false;
+        }
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfBufferException.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfBufferException.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfBufferException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfBufferException.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,41 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.IOException;
+
+/**
+ * This class represents the exception signalizing that
+ * data could not be read from the stream because
+ * underlying input stream reached its end.
+ */
+public class EndOfBufferException extends IOException {
+
+    /**
+     * Constructor
+     */
+    public EndOfBufferException() {
+        super();
+    }
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfSourceException.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfSourceException.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfSourceException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/EndOfSourceException.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,41 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.IOException;
+
+/**
+ * This class represents the exception signalizing that
+ * data could not be read from the buffered stream because
+ * underlying data buffer was exhausted.
+ */
+public class EndOfSourceException extends IOException {
+
+    /**
+     * Constructor
+     */
+    public EndOfSourceException() {
+        super();
+    }
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Finished.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Finished.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Finished.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Finished.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,82 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+* @author Boris Kuznetsov
+* @version $Revision$
+*/
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.IOException;
+
+/**
+ * 
+ * Represents Finished message
+ * @see TLS 1.0 spec., 7.4.9. Finished
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public class Finished extends Message {
+    
+    // verify data
+    private byte[] data;
+    
+    /**
+     * Creates outbound message
+     * @param bytes
+     */
+    public Finished(byte[] bytes) {
+        data = bytes;
+        length = data.length;
+    }
+    
+    /**
+     * Creates inbound message
+     * @param in
+     * @param length
+     * @throws IOException
+     */
+    public Finished(HandshakeIODataStream in, int length)  
+            throws IOException {
+        if (length == 12 || length == 36) {
+            data = in.read(length);
+            length = data.length;
+        } else {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect Finished");
+        }
+    }
+
+    public void send(HandshakeIODataStream out) {
+        out.write(data);
+    }
+    
+    /**
+     * Returns message type 
+     * @return
+     */
+    public int getType() {
+        return Handshake.FINISHED;
+    }
+    
+    /**
+     * Returns verify data
+     * @return
+     */
+    public byte[] getData() {
+        return data;
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Handshake.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Handshake.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Handshake.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Handshake.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,93 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+/**
+ * 
+ * This class incapsulates the constants determining the types of handshake
+ * messages as defined in TLS 1.0 spec., 7.4. Handshake protocol.
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public class Handshake {
+
+    /**
+     * 
+     * hello_request handshake type
+     */
+    public static final byte HELLO_REQUEST = 0;
+
+    /**
+     * 
+     * client_hello handshake type
+     */
+    public static final byte CLIENT_HELLO = 1;
+
+    /**
+     * 
+     * server_hello handshake type
+     */
+    public static final byte SERVER_HELLO = 2;
+
+    /**
+     * 
+     * certificate handshake type
+     */
+    public static final byte CERTIFICATE = 11;
+
+    /**
+     * 
+     * server_key_exchange  handshake type
+     */
+    public static final byte SERVER_KEY_EXCHANGE = 12;
+
+    /**
+     * 
+     * certificate_request handshake type
+     */
+    public static final byte CERTIFICATE_REQUEST = 13;
+
+    /**
+     * 
+     * server_hello_done handshake type
+     */
+    public static final byte SERVER_HELLO_DONE = 14;
+
+    /**
+     * 
+     * certificate_verify handshake type
+     */
+    public static final byte CERTIFICATE_VERIFY = 15;
+
+    /**
+     * 
+     * client_key_exchange handshake type
+     */
+    public static final byte CLIENT_KEY_EXCHANGE = 16;
+
+    /**
+     * 
+     * finished handshake type
+     */
+    public static final byte FINISHED = 20;
+
+}
\ No newline at end of file

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeIODataStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeIODataStream.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeIODataStream.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeIODataStream.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,434 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import javax.net.ssl.SSLHandshakeException;
+
+/**
+ * This class provides Input/Output data functionality
+ * for handshake layer. It provides read and write operations
+ * and accumulates all sent/received handshake's data.
+ * This class can be presented as a combination of 2 data pipes.
+ * The first data pipe is a pipe of income data: append method
+ * places the data at the beginning of the pipe, and read methods
+ * consume the data from the pipe. The second pipe is an outcoming
+ * data pipe: write operations plases the data into the pipe,
+ * and getData methods consume the data.
+ * It is important to note that work with pipe cound not be
+ * started if there is unconsumed data in another pipe. It is
+ * reasoned by the following: handshake protocol performs read
+ * and write operations consecuently. I.e. it first reads all
+ * income data and only than produces the responce and places it
+ * into the stream.
+ * The read operations of the stream presented by the methods
+ * of SSLInputStream which in its turn is an extension of InputStream.
+ * So this stream can be used as an InputStream parameter for
+ * certificate generation.
+ * Also input stream functionality supports marks. The marks
+ * help to reset the position of the stream in case of incompleate
+ * handshake records. Note that in case of exhausting
+ * of income data the EndOfBufferException is thown which implies
+ * the following:
+ *  1. the stream contains scrappy handshake record,
+ *  2. the read position should be reseted to marked,
+ *  3. and more income data is expected.
+ * The throwing of the exception (instead of returning of -1 value
+ * or incompleate filling of destination buffer)
+ * helps to speed up the process of scrappy data recognition and
+ * processing.
+ * For more information about TLS handshake process see
+ * TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt.
+ */
+public class HandshakeIODataStream
+        extends SSLInputStream implements Appendable, DataStream {
+
+    // Objects are used to compute digests of data passed
+    // during the handshake phase
+    private static final MessageDigest md5;
+    private static final MessageDigest sha;
+
+    static {
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(
+                    "Could not initialize the Digest Algorithms.");
+        }
+    }
+
+    public HandshakeIODataStream() {}
+
+    // buffer is used to keep the handshaking data;
+    private int buff_size = 1024;
+    private int inc_buff_size = 1024;
+    private byte[] buffer = new byte[buff_size];
+
+
+    // ---------------- Input related functionality -----------------
+
+    // position of the next byte to read
+    private int read_pos;
+    private int marked_pos;
+    // position of the last byte to read + 1
+    private int read_pos_end;
+
+    public int available() {
+        return read_pos_end - read_pos;
+    }
+
+    public boolean markSupported() {
+        return true;
+    }
+
+    public void mark(int limit) {
+        marked_pos = read_pos;
+    }
+
+    public void mark() {
+        marked_pos = read_pos;
+    }
+
+    public void reset() {
+        read_pos = marked_pos;
+    }
+
+    /**
+     * Removes the data from the marked position to
+     * the current read position. The method is usefull when it is needed
+     * to delete one message from the internal buffer.
+     */
+    protected void removeFromMarkedPosition() {
+        System.arraycopy(buffer, read_pos, 
+                buffer, marked_pos, read_pos_end - read_pos);
+        read_pos_end -= (read_pos - marked_pos);
+        read_pos = marked_pos;
+    }
+
+    /**
+     * read an opaque value;
+     * @param   byte:   byte
+     * @return
+     */
+    public int read() throws IOException {
+        if (read_pos == read_pos_end) {
+            //return -1;
+            throw new EndOfBufferException();
+        }
+        return buffer[read_pos++] & 0xFF;
+    }
+
+    /**
+     * reads vector of opaque values
+     * @param   new:    long
+     * @return
+     */
+    public byte[] read(int length) throws IOException {
+        if (length > available()) {
+            throw new EndOfBufferException();
+        }
+        byte[] res = new byte[length];
+        System.arraycopy(buffer, read_pos, res, 0, length);
+        read_pos = read_pos + length;
+        return res;
+    }
+
+    public int read(byte[] dest, int offset, int length) throws IOException {
+        if (length > available()) {
+            throw new EndOfBufferException();
+        }
+        System.arraycopy(buffer, read_pos, dest, offset, length);
+        read_pos = read_pos + length;
+        return length;
+    }
+
+    // ------------------- Extending of the input data ---------------------
+
+    /**
+     * Appends the income data to be read by handshake protocol.
+     * The attempts to overflow the buffer by meens of this methos
+     * seem to be futile because of:
+     * 1. The SSL protocol specifies the maximum size of the record
+     * and record protocol does not pass huge messages. 
+     * (see TLS v1 specification http://www.ietf.org/rfc/rfc2246.txt ,
+     * p 6.2)
+     * 2. After each call of this method, handshake protocol should
+     * start (and starts) the operations on received data and recognize
+     * the fake data if such was provided (to check the size of certificate
+     * for example).
+     */
+    public void append(byte[] src) {
+        append(src, 0, src.length);
+    }
+
+    private void append(byte[] src, int from, int length) {
+        if (read_pos == read_pos_end) {
+            // start reading state after writing
+            if (write_pos_beg != write_pos) {
+                // error: outboud handshake data was not sent,
+                // but inbound handshake data has been received.
+                throw new AlertException(
+                    AlertProtocol.UNEXPECTED_MESSAGE,
+                    new SSLHandshakeException(
+                        "Handshake message has been received before "
+                        + "the last oubound message had been sent."));
+            }
+            if (read_pos < write_pos) {
+                read_pos = write_pos;
+                read_pos_end = read_pos;
+            }
+        }
+        if (read_pos_end + length > buff_size) {
+            enlargeBuffer(read_pos_end+length-buff_size);
+        }
+        System.arraycopy(src, from, buffer, read_pos_end, length);
+        read_pos_end += length;
+    }
+
+    private void enlargeBuffer(int size) {
+        buff_size = (size < inc_buff_size)
+            ? buff_size + inc_buff_size
+            : buff_size + size;
+        byte[] new_buff = new byte[buff_size];
+        System.arraycopy(buffer, 0, new_buff, 0, buffer.length);
+        buffer = new_buff;
+    }
+    
+    protected void clearBuffer() {
+        read_pos = 0;
+        marked_pos = 0;
+        read_pos_end = 0;
+        write_pos = 0;
+        write_pos_beg = 0;
+        Arrays.fill(buffer, (byte) 0);
+    }
+
+    // ------------------- Output related functionality --------------------
+
+    // position in the buffer available for write
+    private int write_pos;
+    // position in the buffer where the last write session has begun
+    private int write_pos_beg;
+
+    // checks if the data can be written in the buffer
+    private void check(int length) {
+        // (write_pos == write_pos_beg) iff:
+        // 1. there were not write operations yet
+        // 2. all written data was demanded by getData methods
+        if (write_pos == write_pos_beg) {
+            // just started to write after the reading
+            if (read_pos != read_pos_end) {
+                // error: attempt to write outbound data into the stream before
+                // all the inbound handshake data had been read
+                throw new AlertException(
+                        AlertProtocol.INTERNAL_ERROR,
+                        new SSLHandshakeException("Data was not fully read: "
+                        + read_pos + " " + read_pos_end));
+            }
+            // set up the write positions
+            if (write_pos_beg < read_pos_end) {
+                write_pos_beg = read_pos_end;
+                write_pos = write_pos_beg;
+            }
+        }
+        // if there is not enought free space in the buffer - enlarge it:
+        if (write_pos + length >= buff_size) {
+            enlargeBuffer(length);
+        }
+    }
+
+    /**
+     * Writes an opaque value
+     * @param   byte:   byte
+     */
+    public void write(byte b) {
+        check(1);
+        buffer[write_pos++] = b;
+    }
+
+    /**
+     * Writes Uint8 value
+     * @param long: the value to be written (last byte)
+     */
+    public void writeUint8(long n) {
+        check(1);
+        buffer[write_pos++] = (byte) (n & 0x00ff);
+    }
+
+    /**
+     * Writes Uint16 value
+     * @param long: the value to be written (last 2 bytes)
+     */
+    public void writeUint16(long n) {
+        check(2);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
+        buffer[write_pos++] = (byte) (n & 0x00ff);
+    }
+
+    /**
+     * Writes Uint24 value
+     * @param long: the value to be written (last 3 bytes)
+     */
+    public void writeUint24(long n) {
+        check(3);
+        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
+        buffer[write_pos++] = (byte) (n & 0x00ff);
+    }
+
+    /**
+     * Writes Uint32 value
+     * @param long: the value to be written (last 4 bytes)
+     */
+    public void writeUint32(long n) {
+        check(4);
+        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
+        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
+        buffer[write_pos++] = (byte) (n & 0x00ff);
+    }
+
+    /**
+     * Writes Uint64 value
+     * @param long: the value to be written
+     */
+    public void writeUint64(long n) {
+        check(8);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00000000000000L) >> 56);
+        buffer[write_pos++] = (byte) ((n & 0x00ff000000000000L) >> 48);
+        buffer[write_pos++] = (byte) ((n & 0x00ff0000000000L) >> 40);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00000000L) >> 32);
+        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
+        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
+        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
+        buffer[write_pos++] = (byte) (n & 0x00ff);
+    }
+
+    /**
+     * writes vector of opaque values
+     * @param  vector the vector to be written
+     */
+    public void write(byte[] vector) {
+        check(vector.length);
+        System.arraycopy(vector, 0, buffer, write_pos, vector.length);
+        write_pos += vector.length;
+    }
+
+    // ------------------- Retrieve the written bytes ----------------------
+
+    public boolean hasData() {
+        return (write_pos > write_pos_beg);
+    }
+
+    /**
+     * returns the chunk of stored data with the length no more than specified.
+     * @param   length: int
+     * @return
+     */
+    public byte[] getData(int length) {
+        byte[] res;
+        if (write_pos - write_pos_beg < length) {
+            res = new byte[write_pos - write_pos_beg];
+            System.arraycopy(buffer, write_pos_beg,
+                    res, 0, write_pos-write_pos_beg);
+            write_pos_beg = write_pos;
+        } else {
+            res = new byte[length];
+            System.arraycopy(buffer, write_pos_beg, res, 0, length);
+            write_pos_beg += length;
+        }
+        return res;
+    }
+
+    // ---------------------- Debud functionality -------------------------
+
+    protected void printContent(PrintStream outstream) {
+        int perLine = 20;
+        String prefix = " ";
+        String delimiter = "";
+
+        for (int i=write_pos_beg; i<write_pos; i++) {
+            String tail = Integer.toHexString(
+                    0x00ff & buffer[i]).toUpperCase();
+            if (tail.length() == 1) {
+                tail = "0" + tail;
+            }
+            outstream.print(prefix + tail + delimiter);
+
+            if (((i-write_pos_beg+1)%10) == 0) {
+                outstream.print(" ");
+            }
+
+            if (((i-write_pos_beg+1)%perLine) == 0) {
+                outstream.println();
+            }
+        }
+        outstream.println();
+    }
+
+    // ---------------------- Message Digest Functionality ----------------
+
+    /**
+     * Returns the MD5 digest of the data passed throught the stream
+     * @return MD5 digest
+     */
+    protected byte[] getDigestMD5() {
+        synchronized (md5) {
+            int len = (read_pos_end > write_pos)
+                ? read_pos_end
+                : write_pos;
+            md5.update(buffer, 0, len);
+            return md5.digest();
+        }
+    }
+
+    /**
+     * Returns the SHA-1 digest of the data passed throught the stream
+     * @return SHA-1 digest
+     */
+    protected byte[] getDigestSHA() {
+        synchronized (sha) {
+            int len = (read_pos_end > write_pos)
+                ? read_pos_end
+                : write_pos;
+            sha.update(buffer, 0, len);
+            return sha.digest();
+        }
+    }
+
+    /**
+     * Returns all the data passed throught the stream
+     * @return all the data passed throught the stream at the moment
+     */
+    protected byte[] getMessages() {
+        int len = (read_pos_end > write_pos) ? read_pos_end : write_pos;
+        byte[] res = new byte[len];
+        System.arraycopy(buffer, 0, res, 0, len);
+        return res;
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeProtocol.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeProtocol.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeProtocol.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HandshakeProtocol.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,536 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.RSAKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.Arrays;
+import java.util.Vector;
+
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+
+/**
+ * Base class for ClientHandshakeImpl and ServerHandshakeImpl classes.
+ * @see TLS 1.0 spec., 7.4. Handshake protocol
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public abstract class HandshakeProtocol {
+
+    /**
+     * Handshake status NEED_UNWRAP - HandshakeProtocol needs to receive data 
+     */
+    public final static int NEED_UNWRAP = 1;
+    
+    /**
+     * Handshake status NOT_HANDSHAKING - is not currently handshaking
+     */
+    public final static int NOT_HANDSHAKING = 2;
+    
+    /**
+     * Handshake status FINISHED - HandshakeProtocol has just finished 
+     */
+    public final static int FINISHED = 3;
+    
+    /**
+     * Handshake status NEED_TASK - HandshakeProtocol needs the results of delegated task
+     */
+    public final static int NEED_TASK = 4;
+
+    /**
+     * Current handshake status
+     */ 
+    protected int status = NOT_HANDSHAKING;
+
+    /**
+     * IO stream for income/outcome handshake data
+     */
+    protected HandshakeIODataStream io_stream = new HandshakeIODataStream();
+
+    /**
+     * SSL Record Protocol implementation.
+     */
+    protected SSLRecordProtocol recordProtocol;
+
+    /**
+     * SSLParameters suplied by SSLSocket or SSLEngine
+     */
+    protected SSLParameters parameters;
+    
+    /**
+     * Delegated tasks for this handshake implementation
+     */
+    protected Vector delegatedTasks = new Vector();
+    
+    /**
+     * Indicates non-blocking handshake
+     */
+    protected boolean nonBlocking;
+
+    /**
+     * Pending session
+     */ 
+    protected SSLSessionImpl session;
+
+    /**
+     * Sended and received handshake messages
+     */ 
+    protected ClientHello clientHello;
+    protected ServerHello serverHello;
+    protected CertificateMessage serverCert;
+    protected ServerKeyExchange serverKeyExchange;
+    protected CertificateRequest certificateRequest;
+    protected ServerHelloDone serverHelloDone;
+    protected CertificateMessage clientCert;
+    protected ClientKeyExchange clientKeyExchange;
+    protected CertificateVerify certificateVerify;
+    protected Finished clientFinished;
+    protected Finished serverFinished;
+    
+    /**
+     * Indicates that change cipher spec message has been received
+     */
+    protected boolean changeCipherSpecReceived = false;
+
+    /**
+     * Indicates previous session resuming
+     */
+    protected boolean isResuming = false;
+
+    /**
+     *  Premaster secret
+     */
+    protected byte[] preMasterSecret;
+    
+    /**
+     * Exception occured in delegated task
+     */
+    protected Exception delegatedTaskErr;
+
+    // reference verify_data used to verify finished message
+    private byte[] verify_data = new byte[12];
+
+    // Encoding of "master secret" string: "master secret".getBytes()
+    private byte[] master_secret_bytes = 
+            {109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };
+
+    // indicates whether protocol needs to send change cipher spec message
+    private boolean needSendCCSpec = false;
+
+    // indicates whether protocol needs to send change cipher spec message
+    protected boolean needSendHelloRequest = false;
+
+    /**
+     * SSLEngine owning this HandshakeProtocol
+     */ 
+    public SSLEngineImpl engineOwner;
+    
+    /**
+     * SSLSocket owning this HandshakeProtocol
+     */
+    public SSLSocketImpl socketOwner;
+    
+    /**
+     * Creates HandshakeProtocol instance
+     * @param owner
+     */
+    protected HandshakeProtocol(Object owner) {
+        if (owner instanceof SSLEngineImpl) {
+            engineOwner = (SSLEngineImpl) owner;
+            nonBlocking = true;
+            this.parameters = (SSLParameters) engineOwner.sslParameters;
+        } else if (owner instanceof SSLSocketImpl) {
+            socketOwner = (SSLSocketImpl) owner;
+            nonBlocking = false;
+            this.parameters = (SSLParameters) socketOwner.sslParameters;
+        }
+    }
+
+    /**
+     * Sets SSL Record Protocol
+     * @param recordProtocol
+     */
+    public void setRecordProtocol(SSLRecordProtocol recordProtocol) {
+        this.recordProtocol = recordProtocol;
+    }
+    
+    /**
+     * Start session negotiation
+     * @param session
+     */
+    public abstract void start();
+
+    /**
+     * Stops the current session renegotiation process. 
+     * Such functionality is needed when it is session renegotiation 
+     * process and no_renegotiation alert message is received
+     * from another peer.
+     * @param session
+     */
+    protected void stop() {
+        clearMessages();
+        status = NOT_HANDSHAKING;
+    }
+
+    /**
+     * Returns handshake status
+     * @return
+     */
+    public SSLEngineResult.HandshakeStatus getStatus() {
+        if (io_stream.hasData() || needSendCCSpec || 
+                needSendHelloRequest || delegatedTaskErr != null) {
+            return SSLEngineResult.HandshakeStatus.NEED_WRAP;
+        }
+        if (!delegatedTasks.isEmpty()) {
+            return SSLEngineResult.HandshakeStatus.NEED_TASK;
+        }
+
+        switch (status) {
+        case HandshakeProtocol.NEED_UNWRAP:
+            return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
+        case HandshakeProtocol.FINISHED:
+            status = NOT_HANDSHAKING;
+            clearMessages();
+            return SSLEngineResult.HandshakeStatus.FINISHED;
+        default: // HandshakeProtocol.NOT_HANDSHAKING:
+            return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
+        }
+    }
+
+    /**
+     * Returns pending session
+     * @return session
+     */
+    public SSLSessionImpl getSession() {
+        return session;
+    }
+
+    protected void sendChangeCipherSpec() {
+        needSendCCSpec = true;
+    }
+
+    protected void sendHelloRequest() {
+        needSendHelloRequest = true;
+    }
+
+    /**
+     * Proceses inbound ChangeCipherSpec message
+     */
+    abstract void receiveChangeCipherSpec();
+
+    /**
+     * Creates and sends finished message
+     */
+    abstract void makeFinished();
+
+    /**
+     * Proceses inbound handshake messages
+     * @param bytes
+     */
+    public abstract void unwrap(byte[] bytes);
+
+    /**
+     * Processes SSLv2 Hello message
+     * @param bytes
+     */
+    public abstract void unwrapSSLv2(byte[] bytes);
+
+    /**
+     * Proceses outbound handshake messages
+     * @return
+     */
+    public byte[] wrap() {
+        if (delegatedTaskErr != null) {
+            // process error occured in delegated task
+            Exception e = delegatedTaskErr;
+            delegatedTaskErr = null;
+            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                    "Error occured in delegated task:" + e.getMessage(), e);
+        }
+        if (io_stream.hasData()) {
+            return recordProtocol.wrap(ContentType.HANDSHAKE, io_stream);
+        } else if (needSendCCSpec) {
+            makeFinished();
+            needSendCCSpec = false;
+            return recordProtocol.getChangeCipherSpecMesage(getSession());
+        } else if (needSendHelloRequest) {
+            needSendHelloRequest = false;
+            return recordProtocol.wrap(ContentType.HANDSHAKE, 
+                    // hello request message 
+                    // (see TLS v 1 specification: 
+                    // http://www.ietf.org/rfc/rfc2246.txt)
+                    new byte[] {0, 0, 0, 0}, 0, 4);
+        } else {
+            return null; // nothing to send;
+        }
+    }
+
+    /**
+     * Sends fatal alert, breaks execution
+     * 
+     * @param description
+     */
+    protected void sendWarningAlert(byte description) {
+        recordProtocol.alert(AlertProtocol.WARNING, description);
+    }
+
+    /**
+     * Sends fatal alert, breaks execution
+     * 
+     * @param description
+     * @param reason
+     */
+    protected void fatalAlert(byte description, String reason) {
+        throw new AlertException(description, new SSLHandshakeException(reason));
+    }
+
+    /**
+     * Sends fatal alert, breaks execution
+     * 
+     * @param description
+     * @param reason
+     * @param cause
+     */
+    protected void fatalAlert(byte description, String reason, Exception cause) {
+        throw new AlertException(description, new SSLException(reason, cause));
+    }
+
+    /**
+     * Sends fatal alert, breaks execution
+     * 
+     * @param description
+     * @param cause
+     */
+    protected void fatalAlert(byte description, SSLException cause) {
+        throw new AlertException(description, cause);
+    }
+
+    /**
+     * Computers reference TLS verify_data that is used to verify finished message
+     * @see TLS spec. 7.4.9. Finished
+     * @param label
+     */
+    protected void computerReferenceVerifyDataTLS(String label) {
+        computerVerifyDataTLS(label, verify_data);
+    }
+
+    /**
+     * Computer TLS verify_data
+     * @see TLS spec. 7.4.9. Finished
+     * @param label
+     * @param buf
+     */
+    protected void computerVerifyDataTLS(String label, byte[] buf) {
+        byte[] md5_digest = io_stream.getDigestMD5();
+        byte[] sha_digest = io_stream.getDigestSHA();
+
+        byte[] digest = new byte[md5_digest.length + sha_digest.length];
+        System.arraycopy(md5_digest, 0, digest, 0, md5_digest.length);
+        System.arraycopy(sha_digest, 0, digest, md5_digest.length,
+                sha_digest.length);
+        try {
+            PRF.computePRF(buf, session.master_secret, 
+                    label.getBytes(), digest);
+        } catch (GeneralSecurityException e) {
+            fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
+        }
+    }
+
+    /**
+     * Computer reference SSLv3 verify_data that is used to verify finished message
+     * @see SSLv3 spec. 7.6.9. Finished
+     * @param label
+     */
+    protected void computerReferenceVerifyDataSSLv3(byte[] sender) {
+        verify_data = new byte[36];
+        computerVerifyDataSSLv3(sender, verify_data);
+    }
+
+    /**
+     * Computer SSLv3 verify_data
+     * @see SSLv3 spec. 7.6.9. Finished
+     * @param label
+     * @param buf
+     */
+    protected void computerVerifyDataSSLv3(byte[] sender, byte[] buf) {
+        MessageDigest md5;
+        MessageDigest sha;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (Exception e) {
+            fatalAlert(AlertProtocol.INTERNAL_ERROR, "Could not initialize the Digest Algorithms.", e);
+            return;
+        }
+        try {
+            byte[] hanshake_messages = io_stream.getMessages();
+            md5.update(hanshake_messages);
+            md5.update(sender);
+            md5.update(session.master_secret);
+            byte[] b = md5.digest(SSLv3Constants.MD5pad1);
+            md5.update(session.master_secret);
+            md5.update(SSLv3Constants.MD5pad2);
+            System.arraycopy(md5.digest(b), 0, buf, 0, 16);
+
+            sha.update(hanshake_messages);
+            sha.update(sender);
+            sha.update(session.master_secret);
+            b = sha.digest(SSLv3Constants.SHApad1);
+            sha.update(session.master_secret);
+            sha.update(SSLv3Constants.SHApad2);
+            System.arraycopy(sha.digest(b), 0, buf, 16, 20);
+        } catch (Exception e) {
+            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
+
+        }
+    }
+
+    /**
+     * Verifies finished data
+     * 
+     * @param data
+     * @param isServer
+     */
+    protected void verifyFinished(byte[] data) {
+        if (!Arrays.equals(verify_data, data)) {
+            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Incorrect FINISED");
+        }
+    }
+
+    /**
+     * Sends fatal alert "UNEXPECTED MESSAGE"
+     *  
+     */
+    protected void unexpectedMessage() {
+        fatalAlert(AlertProtocol.UNEXPECTED_MESSAGE, "UNEXPECTED MESSAGE");
+    }
+
+    /**
+     * Writes message to HandshakeIODataStream
+     * 
+     * @param message
+     */
+    public void send(Message message) {
+        io_stream.writeUint8(message.getType());
+        io_stream.writeUint24(message.length());
+        message.send(io_stream);
+    }
+
+    /**
+     * Computers master secret
+     *  
+     */
+    public void computerMasterSecret() {
+        byte[] seed = new byte[64];
+        System.arraycopy(clientHello.getRandom(), 0, seed, 0, 32);
+        System.arraycopy(serverHello.getRandom(), 0, seed, 32, 32);
+        session.master_secret = new byte[48];
+        if (serverHello.server_version[1] == 1) { // TLSv1
+            try {
+                PRF.computePRF(session.master_secret, preMasterSecret,
+                        master_secret_bytes, seed);
+            } catch (GeneralSecurityException e) {
+                fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
+            }
+        } else { // SSL3.0
+            PRF.computePRF_SSLv3(session.master_secret, preMasterSecret, seed);
+        }
+        
+        //delete preMasterSecret from memory
+        Arrays.fill(preMasterSecret, (byte)0);
+        preMasterSecret = null;        
+    }
+    
+    /**
+     * Returns a delegated task.
+     * @return Delegated task or null
+     */
+    public Runnable getTask() {
+        if (delegatedTasks.isEmpty()) {
+            return null;
+        } else {
+            Runnable task = (Runnable)delegatedTasks.firstElement();
+            delegatedTasks.remove(0);
+            return task;
+        }
+    }
+    
+    /**
+     * 
+     * Clears previously sended and received handshake messages
+     */
+    protected void clearMessages() {
+        io_stream.clearBuffer();
+        clientHello = null;
+        serverHello = null;
+        serverCert = null;
+        serverKeyExchange = null;
+        certificateRequest = null;
+        serverHelloDone = null;
+        clientCert = null;
+        clientKeyExchange = null;
+        certificateVerify = null;
+        clientFinished = null;
+        serverFinished = null;
+    }
+    
+    /**
+     * Returns RSA key length
+     * @param pk
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    protected static int getRSAKeyLength(PublicKey pk)
+            throws NoSuchAlgorithmException, InvalidKeySpecException {
+
+        BigInteger mod;
+        if (pk instanceof RSAKey) {
+            mod = ((RSAKey) pk).getModulus();
+        } else {
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            mod = ((RSAPublicKeySpec) kf.getKeySpec(pk, RSAPublicKeySpec.class))
+                    .getModulus();
+        }
+        return mod.bitLength();
+    }
+    
+    /**
+     * Shutdownes the protocol. It will be impossiblke to use the instance
+     * after the calling of this method.
+     */
+    protected void shutdown() {
+        clearMessages();
+        session = null;
+        preMasterSecret = null;
+        delegatedTasks.clear();
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HelloRequest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HelloRequest.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HelloRequest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/HelloRequest.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,73 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+* @author Boris Kuznetsov
+* @version $Revision$
+*/
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.IOException;
+
+/**
+ * 
+ * Represents Hello Request message
+ * @see TLS 1.0 spec., 7.4.1.1. Hello request
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public class HelloRequest extends Message {
+    
+    /**
+     * Creates outbound message
+     *
+     */
+    public HelloRequest() {
+    }
+    
+    /**
+     * Creates inbound message
+     * @param in
+     * @param length
+     * @throws IOException
+     */
+    public HelloRequest(HandshakeIODataStream in, int length)  
+            throws IOException {
+        if (length != 0) {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect HelloRequest");
+        }
+    }
+    
+    /**
+     * Sends message
+     * @param out
+     */
+    public void send(HandshakeIODataStream out) {
+    }
+
+    public int length() {
+        return 0;
+    } 
+    
+    /**
+     * Returns message type 
+     * @return
+     */
+    public int getType() {
+        return Handshake.HELLO_REQUEST;
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/JSSEProvider.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/JSSEProvider.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/JSSEProvider.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/JSSEProvider.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,122 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.security.AccessController;
+import java.security.Provider;
+
+/**
+ * JSSE Provider implementation.
+ * 
+ * This implementation is based on TLS v 1.0 and SSL v3 protocol specifications.
+ * 
+ * @see TLS v 1.0 Protocol specification (http://www.ietf.org/rfc/rfc2246.txt)
+ * @see SSL v3 Protocol specification (http://wp.netscape.com/eng/ssl3)
+ * 
+ * Provider implementation supports the following  cipher suites:
+ *     TLS_NULL_WITH_NULL_NULL
+ *     TLS_RSA_WITH_NULL_MD5
+ *     TLS_RSA_WITH_NULL_SHA
+ *     TLS_RSA_EXPORT_WITH_RC4_40_MD5
+ *     TLS_RSA_WITH_RC4_128_MD5
+ *     TLS_RSA_WITH_RC4_128_SHA
+ *     TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+ *     TLS_RSA_WITH_IDEA_CBC_SHA
+ *     TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_RSA_WITH_DES_CBC_SHA
+ *     TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *     TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_DH_DSS_WITH_DES_CBC_SHA
+ *     TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
+ *     TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_DH_RSA_WITH_DES_CBC_SHA
+ *     TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
+ *     TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_DHE_DSS_WITH_DES_CBC_SHA
+ *     TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+ *     TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *     TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *     TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
+ *     TLS_DH_anon_WITH_RC4_128_MD5
+ *     TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+ *     TLS_DH_anon_WITH_DES_CBC_SHA
+ *     TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
+ * 
+ * The real set of availible cipher suites depends on set of availible 
+ * crypto algorithms. These algorithms must be provided by some crypto
+ * provider.
+ * 
+ * The following cipher algorithms are used by different cipher suites:
+ *     IDEA/CBC/NoPadding
+ *     RC2/CBC/NoPadding
+ *     RC4
+ *     DES/CBC/NoPadding
+ *     DES/CBC/NoPadding
+ *     DESede/CBC/NoPadding
+ *  
+ * Also the current JSSE provider implementation uses the following 
+ * crypto algorithms:
+ * 
+ * Algorithms that MUST be provided by crypto provider:
+ *     Mac    HmacMD5
+ *     Mac    HmacSHA1
+ *     MessageDigest    MD5
+ *     MessageDigest    SHA-1
+ *     CertificateFactory    X509
+ * 
+ * The cipher suites with RSA key exchange may also require:
+ *     Cipher    RSA
+ *     KeyPairGenerator    RSA
+ *     KeyFactory    RSA
+ * 
+ * The cipher suites with DH key exchange may also require:
+ *     Signature    NONEwithDSA
+ *     KeyPairGenerator    DiffieHellman or DH
+ *     KeyFactory    DiffieHellman or DH
+ *     KeyAgreement    DiffieHellman or DH
+ *     KeyPairGenerator    DiffieHellman or DH
+ * 
+ * Trust manager implementation requires:
+ *     CertPathValidator    PKIX
+ *     CertificateFactory    X509
+ * 
+ */
+public final class JSSEProvider extends Provider {
+
+    public JSSEProvider() {
+        super("HarmonyJSSE", 1.0, "Harmony JSSE Provider");
+        AccessController.doPrivileged(new java.security.PrivilegedAction() {
+            public Object run() {
+                put("SSLContext.TLS",
+                        "org.apache.harmony.security.provider.jsse.SSLContextImpl");
+                put("Alg.Alias.SSLContext.TLSv1", "TLS");
+                put("KeyManagerFactory.X509",
+                        "org.apache.harmony.security.provider.jsse.KeyManagerFactoryImpl");
+                put("TrustManagerFactory.X509",
+                        "org.apache.harmony.security.provider.jsse.TrustManagerFactoryImpl");
+                return null;
+            }
+        });
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerFactoryImpl.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerFactoryImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerFactoryImpl.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,134 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactorySpi;
+import javax.net.ssl.ManagerFactoryParameters;
+
+/**
+ * KeyManagerFactory implementation.
+ * @see javax.net.ssl.KeyManagerFactorySpi
+ */
+public class KeyManagerFactoryImpl extends KeyManagerFactorySpi {
+
+    // source of key material
+    private KeyStore keyStore;
+
+    //password
+    private char[] pwd;
+
+    /**
+     * @see javax.net.ssl.KeyManagerFactorySpi.engineInit(KeyStore ks, char[]
+     *      password)
+     */
+    public void engineInit(KeyStore ks, char[] password)
+            throws KeyStoreException, NoSuchAlgorithmException,
+            UnrecoverableKeyException {
+        if (ks != null) {
+            keyStore = ks;
+            if (password != null) {
+                pwd = (char[]) password.clone();
+            } else {
+                pwd = new char[0];
+            }
+        } else {
+            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            String keyStoreName = (String) AccessController
+                    .doPrivileged(new java.security.PrivilegedAction() {
+                        public Object run() {
+                            return System.getProperty("javax.net.ssl.keyStore");
+                        }
+                    });
+            String keyStorePwd = null;
+            if (keyStoreName == null || keyStoreName.equalsIgnoreCase("NONE")
+                    || keyStoreName.length() == 0) {
+                try {
+                    keyStore.load(null, null);
+                } catch (IOException e) {
+                    throw new KeyStoreException(e);
+                } catch (CertificateException e) {
+                    throw new KeyStoreException(e);
+                }
+            } else {
+                keyStorePwd = (String) AccessController
+                        .doPrivileged(new java.security.PrivilegedAction() {
+                            public Object run() {
+                                return System
+                                        .getProperty("javax.net.ssl.keyStorePassword");
+                            }
+                        });
+                if (keyStorePwd == null) {
+                    pwd = new char[0];
+                } else {
+                    pwd = keyStorePwd.toCharArray();
+                }
+                try {
+                    keyStore.load(new FileInputStream(new File(keyStoreName)),
+                            pwd);
+
+                } catch (FileNotFoundException e) {
+                    throw new KeyStoreException(e);
+                } catch (IOException e) {
+                    throw new KeyStoreException(e);
+                } catch (CertificateException e) {
+                    throw new KeyStoreException(e);
+                }
+            }
+
+        }
+
+    }
+
+    /**
+     * @see javax.net.ssl.KeyManagerFactorySpi.engineInit(ManagerFactoryParameters
+     *      spec)
+     */
+    public void engineInit(ManagerFactoryParameters spec)
+            throws InvalidAlgorithmParameterException {
+        throw new InvalidAlgorithmParameterException(
+                "ManagerFactoryParameters not supported");
+
+    }
+
+    /**
+     * @see javax.net.ssl.KeyManagerFactorySpi.engineGetKeyManagers()
+     */
+    public KeyManager[] engineGetKeyManagers() {
+        if (keyStore == null) {
+            throw new IllegalStateException("KeyManagerFactory is not initialized");
+        }
+        return new KeyManager[] { new KeyManagerImpl(keyStore, pwd) };
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerImpl.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/KeyManagerImpl.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,241 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+package org.apache.harmony.security.provider.jsse;
+
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * KeyManager implementation.
+ * This implementation uses hashed key store information.
+ * It works faster than retrieving all of the data from the key store.
+ * Any key store changes, that happen after key manager was created, have no effect.
+ * The implementation does not use peer information (host, port)
+ * that may be obtained from socket or engine.
+ * 
+ * @see javax.net.ssl.KeyManager
+ * 
+ */
+public class KeyManagerImpl extends X509ExtendedKeyManager {
+
+    // hashed key store information
+    private final Hashtable hash = new Hashtable();
+
+    /**
+     * Creates Key manager
+     * 
+     * @param keyStore
+     * @param pwd
+     */
+    public KeyManagerImpl(KeyStore keyStore, char[] pwd) {
+        String alias;
+        KeyStore.PrivateKeyEntry entry;
+        Enumeration aliases;
+        try {
+            aliases = keyStore.aliases();
+        } catch (KeyStoreException e) {
+            return;
+        }
+        for (; aliases.hasMoreElements();) {
+            alias = (String) aliases.nextElement();          
+            try {
+                if (keyStore.entryInstanceOf(alias,
+                        KeyStore.PrivateKeyEntry.class)) {
+                    entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
+                            new KeyStore.PasswordProtection(pwd));
+                    hash.put(alias, entry);
+                }
+            } catch (KeyStoreException e) {
+                continue;
+            } catch (UnrecoverableEntryException e) {
+                continue;
+            } catch (NoSuchAlgorithmException e) {
+                continue;
+            }
+        }
+
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.chooseClientAlias(String[]
+     *      keyType, Principal[] issuers, Socket socket)
+     */
+    public String chooseClientAlias(String[] keyType, Principal[] issuers,
+            Socket socket) {
+        String[] al = chooseAlias(keyType, issuers);
+        if (al != null) {
+            return al[0];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.chooseServerAlias(String
+     *      keyType, Principal[] issuers, Socket socket)
+     */
+    public String chooseServerAlias(String keyType, Principal[] issuers,
+            Socket socket) {
+        String[] al = chooseAlias(new String[] { keyType }, issuers);
+        if (al != null) {
+            return al[0];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.getCertificateChain(String
+     *      alias)
+     */
+    public X509Certificate[] getCertificateChain(String alias) {
+        if (hash.containsKey(alias)) {
+            Certificate[] certs = ((KeyStore.PrivateKeyEntry) hash.get(alias))
+                    .getCertificateChain();
+            if (certs[0] instanceof X509Certificate) {
+                X509Certificate[] xcerts = new X509Certificate[certs.length];
+                for (int i = 0; i < certs.length; i++) {
+                    xcerts[i] = (X509Certificate) certs[i];
+                }
+                return xcerts;
+            }
+        }
+        return null;
+
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.getClientAliases(String
+     *      keyType, Principal[] issuers)
+     */
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        return chooseAlias(new String[] { keyType }, issuers);
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.getServerAliases(String
+     *      keyType, Principal[] issuers)
+     */
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        return chooseAlias(new String[] { keyType }, issuers);
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.getPrivateKey(String alias)
+     */
+    public PrivateKey getPrivateKey(String alias) {
+        if (hash.containsKey(alias)) {
+            return ((KeyStore.PrivateKeyEntry) hash.get(alias)).getPrivateKey();
+        }
+        return null;
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.chooseEngineClientAlias(String[]
+     *      keyType, Principal[] issuers, SSLEngine engine)
+     */
+    public String chooseEngineClientAlias(String[] keyType,
+            Principal[] issuers, SSLEngine engine) {
+        String[] al = chooseAlias(keyType, issuers);
+        if (al != null) {
+            return al[0];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.X509ExtendedKeyManager.chooseEngineServerAlias(String
+     *      keyType, Principal[] issuers, SSLEngine engine)
+     */
+    public String chooseEngineServerAlias(String keyType, Principal[] issuers,
+            SSLEngine engine) {
+        String[] al = chooseAlias(new String[] { keyType }, issuers);
+        if (al != null) {
+            return al[0];
+        } else {
+            return null;
+        }
+    }
+
+    private String[] chooseAlias(String[] keyType, Principal[] issuers) {
+        String alias;
+        KeyStore.PrivateKeyEntry entry;
+        
+        if (keyType == null || keyType.length == 0) {
+            return null;
+        }
+        Vector found = new Vector();
+        int count = 0;
+        for (Enumeration aliases = hash.keys(); aliases.hasMoreElements();) {
+            alias = (String) aliases.nextElement();
+            entry = (KeyStore.PrivateKeyEntry) hash.get(alias);
+            Certificate[] certs = entry.getCertificateChain();
+            String alg = certs[0].getPublicKey().getAlgorithm();
+            for (int i = 0; i < keyType.length; i++) {
+                if (alg.equals(keyType[i])) {
+                    if (issuers != null && issuers.length != 0) {
+                        // check that certificate was issued by specified issuer
+                        loop: for (int ii = 0; ii < certs.length; ii++) {
+                            if (certs[ii] instanceof X509Certificate) {
+                                X500Principal issuer = ((X509Certificate) certs[ii])
+                                        .getIssuerX500Principal();
+                                for (int iii = 0; iii < issuers.length; iii++) {
+                                    if (issuer.equals(issuers[iii])) {
+                                        found.add(alias);
+                                        count++;
+                                        break loop;
+                                    }
+                                }
+                            }
+
+                        }
+                    } else {
+                        found.add(alias);
+                        count++;
+                    }
+                }
+            }
+        }
+        if (count > 0) {
+            String[] result = new String[count];
+            found.toArray(result);
+            return result;
+        } else {
+            return null;
+        }
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Logger.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Logger.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Logger.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Logger.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,133 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Alexander Y. Kleymenov
+ * @version $Revision$
+ */
+
+package org.apache.harmony.security.provider.jsse;
+
+import java.io.PrintStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * This class provides debug logging for JSSE provider implementation
+ * TODO: Use java.util.logging
+ */
+public class Logger {
+
+    public static class Stream extends PrintStream {
+        private final String prefix;
+        private static int indent = 0;
+
+        public Stream(String name) {
+            super(System.err);
+            prefix = name + "["+Thread.currentThread().getName()+"] ";
+        }
+
+        public void print(String msg) {
+            for (int i=0; i<indent; i++) {
+                super.print("  ");
+            }
+            super.print(msg);
+        }
+
+        public void newIndent() {
+            indent ++;
+        }
+
+        public void endIndent() {
+            indent --;
+        }
+
+        public void println(String msg) {
+            print(prefix);
+            super.println(msg);
+        }
+
+        public void print(byte[] data) {
+            printAsHex(16, " ", "", data, 0, data.length);
+        }
+
+        public void print(byte[] data, int offset, int len) {
+            printAsHex(16, " ", "", data, offset, len);
+        }
+
+        public void printAsHex(int perLine,
+                String prefix,
+                String delimiter,
+                byte[] data) {
+            printAsHex(perLine, prefix, delimiter, data, 0, data.length);
+        }
+
+        public void printAsHex(int perLine,
+                String prefix,
+                String delimiter,
+                byte[] data, int offset, int len) {
+            String line = "";
+            for (int i=0; i<len; i++) {
+                String tail =
+                    Integer.toHexString(0x00ff & data[i+offset]).toUpperCase();
+                if (tail.length() == 1) {
+                    tail = "0" + tail;
+                }
+                line += prefix + tail + delimiter;
+
+                if (((i+1)%perLine) == 0) {
+                    super.println(line);
+                    line = "";
+                }
+            }
+            super.println(line);
+        }
+    }
+
+    private static String[] names;
+    
+    static {
+        try {
+            names = (String[]) AccessController.doPrivileged(
+                    new PrivilegedAction() {
+                        public Object run() {
+                            return System.getProperty("jsse", "").split(",");
+                        }
+                    });
+            /* 1.5:
+            names = AccessController.doPrivileged(
+                    new PrivilegedAction<String[]>() {
+                        public String[] run() {
+                            return System.getProperty("jsse", "").split(",");
+                        }
+                    }
+                );
+            */
+        } catch (Exception e) {
+            names = new String[0];
+        }
+    }
+
+    public static Stream getStream(String name) {
+        for (int i=0; i<names.length; i++) {
+            if (names[i].equals(name)) {
+                return new Stream(name);
+            }
+        }
+        return null;
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Message.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Message.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Message.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/Message.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,75 @@
+/*
+ *  Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+* @author Boris Kuznetsov
+* @version $Revision$
+*/
+package org.apache.harmony.security.provider.jsse;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+
+/**
+ * 
+ * Base class for handshake messages
+ */
+public abstract class Message {
+    
+    /*
+     * Message length
+     */
+    protected int length;
+    
+    /**
+     * Returns message type 
+     * @return
+     */
+    abstract int getType();
+    
+    /**
+     * Returns message length
+     * @return
+     */
+    public int length() {
+        return length;
+    }
+    
+    /**
+     * Sends message
+     * @param out
+     */
+    abstract void send(HandshakeIODataStream out);
+    
+    /**
+     * Sends fatal alert
+     * @param description
+     * @param reason
+     */
+    protected void fatalAlert(byte description, String reason) {
+        throw new AlertException(description, new SSLHandshakeException(reason));
+    }
+    
+    /**
+     * Sends fatal alert
+     * @param description
+     * @param reason
+     * @param cause
+     */
+    protected void fatalAlert(byte description, String reason, Throwable cause) {
+        throw new AlertException(description, new SSLException(reason, cause));
+    }
+}