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 [2/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/ClientHandshakeImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHandshakeImpl.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHandshakeImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHandshakeImpl.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,620 @@
+/*
+ *  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;
+import java.security.AccessController;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedExceptionAction;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.interfaces.DHKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.X509ExtendedKeyManager;
+
+/**
+ * Client side handshake protocol implementation.
+ * Handshake protocol operates on top of the Record Protocol.
+ * It is responsible for session negotiating.
+ * 
+ * The implementation proceses inbound server handshake messages,
+ * creates and sends respond messages. Outbound messages are supplied 
+ * to Record Protocol. Detected errors are reported to the Alert protocol.
+ * 
+ * @see TLS 1.0 spec., 7. The TLS Handshake Protocol
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ *  
+ */
+public class ClientHandshakeImpl extends HandshakeProtocol {  
+   
+    /**
+     * Creates Client Handshake Implementation
+     * 
+     * @param owner
+     */
+    ClientHandshakeImpl(Object owner) {
+        super(owner);
+    }
+    
+    /**
+     * Starts handshake
+     *
+     */  
+    public void start() {
+        if (session == null) { // initial handshake
+            session = findSessionToResume();
+        } else { // start session renegotiation
+            if (clientHello != null && this.status != FINISHED) {
+                // current negotiation has not completed
+                return; // ignore
+            }
+            if (!session.isValid()) {
+                session = null;
+            }
+        }
+        if (session != null) {
+            isResuming = true;
+        } else if (parameters.getEnableSessionCreation()){    
+            isResuming = false;
+            session = new SSLSessionImpl(parameters.getSecureRandom());
+            session.protocol = ProtocolVersion.getLatestVersion(parameters
+                    .getEnabledProtocols());
+            recordProtocol.setVersion(session.protocol.version);
+        } else {
+            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created ");
+        }
+        startSession();
+    }
+    
+    /**
+     * Starts renegotiation on a new session
+     *
+     */
+    private void renegotiateNewSession() {
+        if (parameters.getEnableSessionCreation()){    
+            isResuming = false;
+            session = new SSLSessionImpl(parameters.getSecureRandom());
+            session.protocol = ProtocolVersion.getLatestVersion(parameters
+                    .getEnabledProtocols());
+            recordProtocol.setVersion(session.protocol.version);
+            startSession();
+        } else {
+            status = NOT_HANDSHAKING;
+            sendWarningAlert(AlertProtocol.NO_RENEGOTIATION);
+        }        
+    }
+
+    /*
+     * Starts/resumes session
+     */
+    private void startSession() {
+        CipherSuite[] cipher_suites;
+        if (isResuming) {
+            cipher_suites = new CipherSuite[] { session.cipherSuite };
+        } else {
+            cipher_suites = parameters.enabledCipherSuites;
+        }
+        clientHello = new ClientHello(parameters.getSecureRandom(),
+                session.protocol.version, session.id, cipher_suites);
+        session.clientRandom = clientHello.random;
+        send(clientHello);
+        status = NEED_UNWRAP;
+    }
+
+    /**
+     * Proceses inbound handshake messages
+     * @param bytes
+     */
+    public void unwrap(byte[] bytes) {
+        if (this.delegatedTaskErr != null) {
+            Exception e = this.delegatedTaskErr;
+            this.delegatedTaskErr = null;
+            this.fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Error in delegated task", e);
+        }
+        int handshakeType;
+        io_stream.append(bytes);
+        while (io_stream.available() > 0) {
+            io_stream.mark();
+            int length;
+            try {
+                handshakeType = io_stream.read();
+                length = io_stream.readUint24();
+                if (io_stream.available() < length) {
+                    io_stream.reset();
+                    return;
+                }
+                switch (handshakeType) {
+                case 0: // HELLO_REQUEST
+                    // we don't need to take this message into account
+                    // during FINISH message verification, so remove it
+                    io_stream.removeFromMarkedPosition();
+                    if (clientHello != null
+                            && (clientFinished == null || serverFinished == null)) {
+                        //currently negotiating - ignore
+                        break;
+                    }
+                    // renegotiate
+                    if (session.isValid()) {
+                        session = (SSLSessionImpl) session.clone();
+                        isResuming = true;
+                        startSession();
+                    } else {
+                        // if SSLSession is invalidated (e.g. timeout limit is
+                        // exceeded) connection can't resume the session.
+                        renegotiateNewSession();
+                    }
+                    break;
+                case 2: // SERVER_HELLO
+                    if (clientHello == null || serverHello != null) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    serverHello = new ServerHello(io_stream, length);
+
+                    //check protocol version
+                    ProtocolVersion servProt = ProtocolVersion
+                            .getByVersion(serverHello.server_version);
+                    String[] enabled = parameters.getEnabledProtocols();        
+                    find: {
+                        for (int i = 0; i < enabled.length; i++) {
+                            if (servProt.equals(ProtocolVersion
+                                    .getByName(enabled[i]))) {
+                                break find;
+                            }
+                        }
+                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                                "Bad server hello protocol version");
+                    }
+                    
+                    // check compression method
+                    if (serverHello.compression_method != 0) {
+                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                                "Bad server hello compression method");
+                    }
+                    
+                    //check cipher_suite
+                    CipherSuite[] enabledSuites = parameters.enabledCipherSuites;
+                    find: {
+                        for (int i = 0; i < enabledSuites.length; i++) {
+                            if (serverHello.cipher_suite
+                                    .equals(enabledSuites[i])) {
+                                break find;
+                            }
+                        }
+                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                                "Bad server hello cipher suite");
+                    }                
+
+                    if (isResuming) {
+                        if (serverHello.session_id.length == 0) {
+                            // server is not willing to establish the new connection
+                            // using specified session
+                            isResuming = false;
+                        } else if (!Arrays.equals(serverHello.session_id, clientHello.session_id)) {
+                            isResuming = false;
+                        } else if (!session.protocol.equals(servProt)) {
+                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                                    "Bad server hello protocol version");                            
+                        } else if (!session.cipherSuite
+                                .equals(serverHello.cipher_suite)) {
+                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
+                                    "Bad server hello cipher suite");
+                        }
+                        if (serverHello.server_version[1] == 1) {
+                            computerReferenceVerifyDataTLS("server finished");
+                        } else {
+                            computerReferenceVerifyDataSSLv3(SSLv3Constants.server);
+                        }
+                    }
+                    session.protocol = servProt;
+                    recordProtocol.setVersion(session.protocol.version);
+                    session.cipherSuite = serverHello.cipher_suite;
+                    session.id = (byte[]) serverHello.session_id.clone();
+                    session.serverRandom = serverHello.random;
+                    break;
+                case 11: // CERTIFICATE
+                    if (serverHello == null || serverKeyExchange != null
+                            || serverCert != null || isResuming) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    serverCert = new CertificateMessage(io_stream, length);
+                    break;
+                case 12: // SERVER_KEY_EXCHANGE
+                    if (serverHello == null || serverKeyExchange != null
+                            || isResuming) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    serverKeyExchange = new ServerKeyExchange(io_stream,
+                            length, session.cipherSuite.keyExchange);
+                    break;
+                case 13: // CERTIFICATE_REQUEST
+                    if (serverCert == null || certificateRequest != null
+                            || session.cipherSuite.isAnonymous() || isResuming) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    certificateRequest = new CertificateRequest(io_stream,
+                            length);
+                    break;
+                case 14: // SERVER_HELLO_DONE
+                    if (serverHello == null || serverHelloDone != null
+                            || isResuming) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    serverHelloDone = new ServerHelloDone(io_stream, length);
+                    if (this.nonBlocking) {
+                        delegatedTasks.add(new DelegatedTask(
+                                new PrivilegedExceptionAction(){ 
+                            public Object run() throws Exception {
+                                processServerHelloDone();
+                                return null;
+                                } 
+                            },
+                            this,
+                            AccessController.getContext()));
+                        return;
+                    }
+                    processServerHelloDone();
+                    break;
+                case 20: // FINISHED
+                    if (!changeCipherSpecReceived) {
+                        unexpectedMessage();
+                        return;
+                    }
+                    serverFinished = new Finished(io_stream, length);
+                    verifyFinished(serverFinished.getData());
+                    session.lastAccessedTime = System.currentTimeMillis();
+                    parameters.getClientSessionContext().putSession(session);
+                    if (isResuming) {
+                        sendChangeCipherSpec();
+                    } else {
+                        session.lastAccessedTime = System.currentTimeMillis();
+                        status = FINISHED;
+                    }
+                    // XXX there is no cleanup work
+                    break;
+                default:
+                    unexpectedMessage();
+                    return;
+                }
+            } catch (IOException e) {
+                // io stream dosn't contain complete handshake message
+                io_stream.reset();
+                return;
+            }
+        }
+
+    }
+
+    /**
+     * Processes SSLv2 Hello message. 
+     * SSLv2 client hello message message is an unexpected message 
+     * for client side of handshake protocol.
+     * @ see TLS 1.0 spec., E.1. Version 2 client hello
+     * @param bytes
+     */
+    public void unwrapSSLv2(byte[] bytes) {
+        unexpectedMessage();
+    }
+
+    /**
+     * Creates and sends Finished message
+     */
+    protected void makeFinished() {
+        byte[] verify_data;
+        if (serverHello.server_version[1] == 1) {
+            verify_data = new byte[12];
+            computerVerifyDataTLS("client finished", verify_data);
+        } else {
+            verify_data = new byte[36];
+            computerVerifyDataSSLv3(SSLv3Constants.client, verify_data);
+        }
+        clientFinished = new Finished(verify_data);
+        send(clientFinished);
+        if (isResuming) {
+            session.lastAccessedTime = System.currentTimeMillis();
+            status = FINISHED;
+        } else {
+            if (serverHello.server_version[1] == 1) {
+                computerReferenceVerifyDataTLS("server finished");
+            } else {
+                computerReferenceVerifyDataSSLv3(SSLv3Constants.server);
+            }
+            status = NEED_UNWRAP;
+        }
+    }
+
+    /**
+     * Processes ServerHelloDone: makes verification of the server messages; sends
+     * client messages, computers masterSecret, sends ChangeCipherSpec
+     */
+    void processServerHelloDone() {
+        if (serverCert != null) {
+            if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon
+                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
+                unexpectedMessage();
+                return;
+            }
+            verifyServerCert();
+        } else {
+            if (session.cipherSuite.keyExchange != CipherSuite.KeyExchange_DH_anon
+                    && session.cipherSuite.keyExchange != CipherSuite.KeyExchange_DH_anon_EXPORT) {
+                unexpectedMessage();
+                return;
+            }
+        }
+
+        // Client certificate
+        if (certificateRequest != null) {
+            X509Certificate[] certs = null;
+            String clientAlias = ((X509ExtendedKeyManager) parameters
+                    .getKeyManager()).chooseClientAlias(certificateRequest
+                    .getTypesAsString(),
+                    certificateRequest.certificate_authorities, null);
+            if (clientAlias != null) {
+                certs = ((X509ExtendedKeyManager) parameters.getKeyManager())
+                        .getCertificateChain((clientAlias));
+            }
+            session.localCertificates = certs;
+            clientCert = new CertificateMessage(certs);
+            send(clientCert);
+        }
+        // Client key exchange
+        if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
+                || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
+            // RSA encrypted premaster secret message
+            Cipher c;
+            try {
+                c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+                if (serverKeyExchange != null) {
+                    c.init(Cipher.ENCRYPT_MODE, serverKeyExchange
+                            .getRSAPublicKey());
+                } else {
+                    c.init(Cipher.ENCRYPT_MODE, serverCert.certs[0]);
+                }
+            } catch (Exception e) {
+                fatalAlert(AlertProtocol.INTERNAL_ERROR,
+                        "Unexpected exception", e);
+                return;
+            }
+            preMasterSecret = new byte[48];
+            parameters.getSecureRandom().nextBytes(preMasterSecret);
+            System.arraycopy(clientHello.client_version, 0, preMasterSecret, 0,
+                    2);
+            try {
+                clientKeyExchange = new ClientKeyExchange(c
+                        .doFinal(preMasterSecret),
+                        serverHello.server_version[1] == 1);
+            } catch (Exception e) {
+                fatalAlert(AlertProtocol.INTERNAL_ERROR,
+                        "Unexpected exception", e);
+                return;
+            }
+        } else {
+            PublicKey serverPublic;
+            KeyAgreement agreement = null;
+            DHParameterSpec spec;
+            try {
+                KeyFactory kf = null;
+                try {
+                    kf = KeyFactory.getInstance("DH");
+                } catch (NoSuchAlgorithmException e) {
+                    kf = KeyFactory.getInstance("DiffieHellman");
+                }
+                
+                try {
+                    agreement = KeyAgreement.getInstance("DH");
+                } catch (NoSuchAlgorithmException ee) {
+                    agreement = KeyAgreement.getInstance("DiffieHellman");
+                }
+
+                KeyPairGenerator kpg = null;
+                try {
+                    kpg = KeyPairGenerator.getInstance("DH");
+                } catch (NoSuchAlgorithmException e) {
+                    kpg = KeyPairGenerator.getInstance("DiffieHellman");
+                }
+                if (serverKeyExchange != null) {
+                    serverPublic = kf.generatePublic(new DHPublicKeySpec(
+                            serverKeyExchange.par3, serverKeyExchange.par1,
+                            serverKeyExchange.par2));
+                    spec = new DHParameterSpec(serverKeyExchange.par1,
+                            serverKeyExchange.par2);
+                } else {
+                    serverPublic = serverCert.certs[0].getPublicKey();
+                    spec = ((DHPublicKey) serverPublic).getParams();
+                }
+                kpg.initialize(spec);
+
+                KeyPair kp = kpg.generateKeyPair();
+                Key key = kp.getPublic();
+                if (clientCert != null
+                        && serverCert != null
+                        && (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
+                                || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS)) {
+                    PublicKey client_pk = clientCert.certs[0].getPublicKey();
+                    PublicKey server_pk = serverCert.certs[0].getPublicKey();
+                    if (client_pk instanceof DHKey
+                            && server_pk instanceof DHKey) {
+                        if (((DHKey) client_pk).getParams().getG().equals(
+                                ((DHKey) server_pk).getParams().getG())
+                                && ((DHKey) client_pk).getParams().getP()
+                                    .equals(((DHKey) server_pk).getParams().getG())) {
+                            // client cert message DH public key parameters
+                            // matched those specified by the
+                            //   server in its certificate,
+                            clientKeyExchange = new ClientKeyExchange(); // empty
+                        }
+                    }
+                } else {
+                    clientKeyExchange = new ClientKeyExchange(
+                            ((DHPublicKey) key).getY());
+                }
+                key = kp.getPrivate();
+                agreement.init(key);
+                agreement.doPhase(serverPublic, true);
+                preMasterSecret = agreement.generateSecret();
+            } catch (Exception e) {
+                fatalAlert(AlertProtocol.INTERNAL_ERROR,
+                        "Unexpected exception", e);
+                return;
+            }
+        }
+        if (clientKeyExchange != null) {
+            send(clientKeyExchange);
+        }
+
+        computerMasterSecret();
+
+        if (clientCert != null) {
+            boolean[] keyUsage = clientCert.certs[0].getKeyUsage();
+            if (keyUsage != null && keyUsage[0]) {
+                // Certificate verify
+                DigitalSignature ds = new DigitalSignature(
+                        session.cipherSuite.keyExchange);
+                if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT
+                        || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
+                        || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
+                    ds.setMD5(io_stream.getDigestMD5());
+                    ds.setSHA(io_stream.getDigestSHA());
+                } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
+                        || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
+                    ds.setSHA(io_stream.getDigestSHA());
+                // The Signature should be empty in case of anonimous signature algorithm:
+                // } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon ||
+                // session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
+                }
+                certificateVerify = new CertificateVerify(ds.sign());
+                send(certificateVerify);
+            }
+        }
+
+        sendChangeCipherSpec();
+    }
+    
+    /*
+     * Verifies certificate path
+     */
+    private void verifyServerCert() {
+        String authType = null;
+        switch (session.cipherSuite.keyExchange) {
+        case 1: // KeyExchange_RSA
+            authType = "RSA";
+            break;
+        case 2: // KeyExchange_RSA_EXPORT
+            if (serverKeyExchange != null ) {
+                // ephemeral RSA key is used 
+                authType = "RSA_EXPORT";
+            } else {
+                authType = "RSA";
+            }
+            break;
+        case 3: // KeyExchange_DHE_DSS
+        case 4: // KeyExchange_DHE_DSS_EXPORT
+            authType = "DHE_DSS";
+            break;
+        case 5: // KeyExchange_DHE_RSA
+        case 6: // KeyExchange_DHE_RSA_EXPORT
+            authType = "DHE_RSA";
+            break;
+        case 7: // KeyExchange_DH_DSS
+        case 11: // KeyExchange_DH_DSS_EXPORT
+            authType = "DH_DSS";
+            break;
+        case 8: // KeyExchange_DH_RSA
+        case 12: // KeyExchange_DH_RSA_EXPORT
+            authType = "DH_RSA";
+            break;
+        case 9: // KeyExchange_DH_anon
+        case 10: // KeyExchange_DH_anon_EXPORT
+            return;
+        }
+        try {
+            parameters.getTrustManager().checkServerTrusted(serverCert.certs,
+                    authType);
+        } catch (CertificateException e) {
+            fatalAlert(AlertProtocol.BAD_CERTIFICATE, "Not trusted server certificate", e);
+            return;
+        }
+        session.peerCertificates = serverCert.certs;
+    }
+
+    /**
+     * Proceses ChangeCipherSpec message
+     */
+    public void receiveChangeCipherSpec() {
+        if (isResuming) {
+            if (serverHello == null) {
+                unexpectedMessage();
+            }
+        } else if (clientFinished == null) {
+            unexpectedMessage();
+        } 
+        changeCipherSpecReceived = true;
+    }
+
+    // Find session to resume in client session context
+    private SSLSessionImpl findSessionToResume() {
+        String host;
+        int port;
+        if (engineOwner != null) {
+            host = engineOwner.getPeerHost();
+            port = engineOwner.getPeerPort();
+        } else {
+            host = socketOwner.getInetAddress().getHostName();
+            port = socketOwner.getPort();
+        }
+        if (host == null || port == -1) {
+            return null; // starts new session
+        }
+        
+        byte[] id;
+        SSLSession ses;
+        SSLSessionContext context = parameters.getClientSessionContext();
+        for (Enumeration en = context.getIds(); en.hasMoreElements();) {
+            id = (byte[])en.nextElement();
+            ses = context.getSession(id);
+            if (host.equals(ses.getPeerHost()) && port == ses.getPeerPort()) {
+                return (SSLSessionImpl)((SSLSessionImpl)ses).clone(); // resume
+            }            
+        }
+        return null; // starts new session
+    }
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHello.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHello.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHello.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientHello.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,209 @@
+/*
+ *  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;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+/**
+ * 
+ * Represents Client Hello message
+ * @see TLS 1.0 spec., 7.4.1.2. Client hello
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public class ClientHello extends Message {
+
+    /**
+     * Client version
+     */
+    final byte[] client_version;
+
+    /**
+     * Random bytes
+     */
+    final byte[] random = new byte[32];
+
+    /**
+     * Session id
+     */
+    final byte[] session_id;
+
+    /**
+     * Cipher suites supported by the client
+     */
+    final CipherSuite[] cipher_suites;
+
+    /**
+     * Compression methods supported by the client
+     */
+    final byte[] compression_methods;
+
+    /**
+     * Creates outbound message
+     * @param sr
+     * @param version
+     * @param ses_id
+     * @param cipher_suite
+     */
+    public ClientHello(SecureRandom sr, byte[] version, byte[] ses_id,
+            CipherSuite[] cipher_suite) {
+        client_version = version;
+        long gmt_unix_time = System.currentTimeMillis()/1000;
+        sr.nextBytes(random);
+        random[0] = (byte) (gmt_unix_time & 0xFF000000 >>> 24);
+        random[1] = (byte) (gmt_unix_time & 0xFF0000 >>> 16);
+        random[2] = (byte) (gmt_unix_time & 0xFF00 >>> 8);
+        random[3] = (byte) (gmt_unix_time & 0xFF);
+        session_id = ses_id;
+        this.cipher_suites = cipher_suite;
+        compression_methods = new byte[] { 0 }; // CompressionMethod.null
+        length = 38 + session_id.length + (this.cipher_suites.length << 1)
+                + compression_methods.length;
+    }
+
+    /**
+     * Creates inbound message
+     * @param in
+     * @param length
+     * @throws IOException
+     */
+    public ClientHello(HandshakeIODataStream in, int length) throws IOException {
+        client_version = new byte[2];
+        client_version[0] = (byte) in.readUint8();
+        client_version[1] = (byte) in.readUint8();
+        in.read(random, 0, 32);
+        int size = in.read();
+        session_id = new byte[size];
+        in.read(session_id, 0, size);
+        int l = in.readUint16();
+        if ((l & 0x01) == 0x01) { // cipher suites length must be an even number
+            fatalAlert(AlertProtocol.DECODE_ERROR,
+                    "DECODE ERROR: incorrect ClientHello");
+        }
+        size = l >> 1;
+        cipher_suites = new CipherSuite[size];
+        for (int i = 0; i < size; i++) {
+            byte b0 = (byte) in.read();
+            byte b1 = (byte) in.read();
+            cipher_suites[i] = CipherSuite.getByCode(b0, b1);
+        }
+        size = in.read();
+        compression_methods = new byte[size];
+        in.read(compression_methods, 0, size);
+        this.length = 38 + session_id.length + (cipher_suites.length << 1)
+                + compression_methods.length;
+        if (this.length > length) {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect ClientHello");
+        }
+        // for forward compatibility, extra data is permitted;
+        // must be ignored
+        if (this.length < length) {
+            in.skip(length - this.length);
+            this.length = length;
+        }
+    }
+    /**
+     * Parse V2ClientHello
+     * @param in
+     * @throws IOException
+     */
+    public ClientHello(HandshakeIODataStream in) throws IOException {
+        if (in.readUint8() != 1) {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect V2ClientHello");
+        }
+        client_version = new byte[2];
+        client_version[0] = (byte) in.readUint8();
+        client_version[1] = (byte) in.readUint8();
+        int cipher_spec_length = in.readUint16();
+        if (in.readUint16() != 0) { // session_id_length
+            // as client already knows the protocol known to a server it should
+            // initiate the connection in that native protocol
+            fatalAlert(AlertProtocol.DECODE_ERROR,
+                    "DECODE ERROR: incorrect V2ClientHello, cannot be used for resuming");
+        }
+        int challenge_length = in.readUint16();
+        if (challenge_length < 16) {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect V2ClientHello, short challenge data");
+        }
+        session_id = new byte[0];
+        cipher_suites = new CipherSuite[cipher_spec_length/3];
+        for (int i = 0; i < cipher_suites.length; i++) {
+            byte b0 = (byte) in.read();
+            byte b1 = (byte) in.read();
+            byte b2 = (byte) in.read();
+            cipher_suites[i] = CipherSuite.getByCode(b0, b1, b2);
+        }
+        compression_methods = new byte[] { 0 }; // CompressionMethod.null
+        
+        if (challenge_length < 32) {
+            Arrays.fill(random, 0, 32 - challenge_length, (byte)0);
+            System.arraycopy(in.read(challenge_length), 0, random, 32 - challenge_length, challenge_length);            
+        } else if (challenge_length == 32) {
+            System.arraycopy(in.read(32), 0, random, 0, 32);            
+        } else {
+            System.arraycopy(in.read(challenge_length), challenge_length - 32, random, 0, 32);
+        }
+        if (in.available() > 0) {
+            fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect V2ClientHello, extra data");
+        }
+        this.length = 38 + session_id.length + (cipher_suites.length << 1)
+                + compression_methods.length;    
+    }
+
+    /**
+     * Sends message
+     * @param out
+     */
+    public void send(HandshakeIODataStream out) {
+        out.write(client_version);
+        out.write(random);
+        out.writeUint8(session_id.length);
+        out.write(session_id);
+        int size = cipher_suites.length << 1;
+        out.writeUint16(size);
+        for (int i = 0; i < cipher_suites.length; i++) {
+            out.write(cipher_suites[i].toBytes());
+        }
+        out.writeUint8(compression_methods.length);
+        for (int i = 0; i < compression_methods.length; i++) {
+            out.write(compression_methods[i]);
+        }
+    }
+
+    /**
+     * Returns client random
+     * @return client random
+     */
+    public byte[] getRandom() {
+        return random;
+    }
+
+    /**
+     * Returns message type 
+     * @return
+     */
+    public int getType() {
+        return Handshake.CLIENT_HELLO;
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientKeyExchange.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientKeyExchange.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientKeyExchange.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ClientKeyExchange.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,151 @@
+/*
+ *  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;
+import java.math.BigInteger;
+
+/**
+ * 
+ * Represents client key exchange message
+ * @see TLS 1.0 spec., 7.4.7. Client key exchange message
+ * (http://www.ietf.org/rfc/rfc2246.txt)
+ * 
+ */
+public class ClientKeyExchange extends Message {
+
+    /**
+     * Exchange keys
+     */
+    final byte[] exchange_keys;
+    
+    /**
+     * Equals true if TLS1.0 protocol is used
+     */
+    boolean isTLS;
+    
+    /**
+     * Equals true if key exchange algorithm is RSA
+     */
+    final boolean isRSA;
+    
+    /**
+     * Creates outbound message
+     * @param encrypted_pre_master_secret
+     * @param isTLS
+     */
+    public ClientKeyExchange(byte[] encrypted_pre_master_secret, boolean isTLS) {
+        this.exchange_keys = encrypted_pre_master_secret;    
+        length = this.exchange_keys.length;
+        if (isTLS) {
+            length += 2;
+        }
+        this.isTLS = isTLS;
+        isRSA = true;
+    }
+    
+    /**
+     * Creates outbound message
+     * @param dh_Yc 
+     */
+    public ClientKeyExchange(BigInteger dh_Yc) {
+        byte[] bb = dh_Yc.toByteArray();
+        if (bb[0] == 0) {
+            exchange_keys = new byte[bb.length-1]; 
+            System.arraycopy(bb, 1, exchange_keys, 0, exchange_keys.length);
+        } else {
+            exchange_keys = bb;
+        }
+        length = exchange_keys.length +2;
+        isRSA = false;
+    }
+    
+    /**
+     * Creates empty message
+     *
+     */
+    public ClientKeyExchange() {
+        exchange_keys = new byte[0];
+        length = 0;
+        isRSA = false;
+    }
+    
+    /**
+     * Creates inbound message
+     * @param length
+     * @param isTLS
+     * @param isRSA
+     * @throws IOException
+     */
+    public ClientKeyExchange(HandshakeIODataStream in, int length, boolean isTLS, boolean isRSA) 
+            throws IOException {
+        this.isTLS = isTLS;
+        this.isRSA = isRSA;
+        if (length == 0) {
+            this.length = 0;
+            exchange_keys = new byte[0];
+        } else {
+            int size;
+            if (isRSA && !isTLS) {// SSL3.0 RSA
+                size = length;
+                this.length = size;
+            } else { // DH or TLSv1 RSA
+                size = in.readUint16();
+                this.length = 2 + size;
+            }
+            exchange_keys = new byte[size];
+            in.read(exchange_keys, 0, size);
+            if (this.length != length) {
+                fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect ClientKeyExchange");
+            }
+        }
+    }
+
+    /**
+     * Sends message
+     * @param out
+     */
+    public void send(HandshakeIODataStream out) {
+        if (exchange_keys.length != 0) {    
+            if (!isRSA || isTLS) {// DH or TLSv1 RSA
+                out.writeUint16(exchange_keys.length);
+            }
+            out.write(exchange_keys);
+        }
+    }
+    
+    /**
+     * Returns message type 
+     * @return
+     */
+    public int getType() {
+        return Handshake.CLIENT_KEY_EXCHANGE;
+    }
+    
+    /**
+     * Returns true if the message is empty (in case of implicit DH Yc)
+     * @return
+     */
+    public boolean isEmpty() {
+        return (exchange_keys.length == 0);
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionState.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionState.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionState.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionState.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,171 @@
+/*
+ *  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 javax.crypto.Cipher;
+
+/**
+ * This abstract class is a base for Record Protocol operating environmet
+ * of different SSL protocol versions.
+ */
+public abstract class ConnectionState {
+
+    /**
+     * The cipher used for encode operations
+     */
+    protected Cipher encCipher;
+
+    /**
+     * The cipher used for decode operations
+     */
+    protected Cipher decCipher;
+
+    /**
+     * The cipher type
+     */
+    protected boolean is_block_cipher;
+
+    /**
+     * The size of MAC used under this connection state
+     */
+    protected int hash_size;
+
+    /**
+     * Write sequence number which is incremented after each
+     * encrypt call
+     */
+    protected final byte[] write_seq_num = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    /**
+     * Read sequence number which is incremented after each
+     * decrypt call
+     */
+    protected final byte[] read_seq_num = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    protected Logger.Stream logger = Logger.getStream("conn_state");
+
+    /**
+     * Returns the minimal possible size of the
+     * Generic[Stream|Generic]Cipher structure under this
+     * connection state.
+     */
+    protected int getMinFragmentSize() {
+        // block ciphers return value with padding included
+        return encCipher.getOutputSize(1+hash_size); // 1 byte for data
+    }
+
+    /**
+     * Returns the size of the Generic[Stream|Generic]Cipher structure
+     * corresponding to the content data of specified size.
+     */
+    protected int getFragmentSize(int content_size) {
+        return encCipher.getOutputSize(content_size+hash_size);
+    }
+
+    /**
+     * Returns the minimal upper bound of the content size enclosed
+     * into the Generic[Stream|Generic]Cipher structure of specified size.
+     * For stream ciphers the returned value will be exact value.
+     */
+    protected int getContentSize(int generic_cipher_size) {
+        //it does not take the padding of block ciphered structures
+        //into account (so returned value can be greater than actual)
+        return decCipher.getOutputSize(generic_cipher_size)-hash_size;
+    }
+
+    /**
+     * Creates the GenericStreamCipher or GenericBlockCipher
+     * data structure for specified data of specified type.
+     * @param type - the ContentType of the provided data
+     * @param fragment - the byte array containing the
+     * data to be encrypted under the current connection state.
+     */
+    protected byte[] encrypt(byte type, byte[] fragment) {
+        return encrypt(type, fragment, 0, fragment.length);
+    }
+
+    /**
+     * Creates the GenericStreamCipher or GenericBlockCipher
+     * data structure for specified data of specified type.
+     * @param type - the ContentType of the provided data
+     * @param fragment - the byte array containing the
+     * data to be encrypted under the current connection state.
+     * @param offset - the offset from which the data begins with.
+     * @param len - the length of the data.
+     */
+    protected abstract byte[] encrypt
+        (byte type, byte[] fragment, int offset, int len);
+
+    /**
+     * Retrieves the fragment of the Plaintext structure of
+     * the specified type from the provided data.
+     * @param type - the ContentType of the data to be decrypted.
+     * @param fragment - the byte array containing the
+     * data to be encrypted under the current connection state.
+     */
+    protected byte[] decrypt(byte type, byte[] fragment) {
+        return decrypt(type, fragment, 0, fragment.length);
+    }
+
+    /**
+     * Retrieves the fragment of the Plaintext structure of
+     * the specified type from the provided data.
+     * @param type - the ContentType of the data to be decrypted.
+     * @param fragment - the byte array containing the
+     * data to be encrypted under the current connection state.
+     * @param offset - the offset from which the data begins with.
+     * @param len - the length of the data.
+     */
+    protected abstract byte[] decrypt
+        (byte type, byte[] fragment, int offset, int len);
+
+    /**
+     * Increments the sequence number.
+     */
+    protected static void incSequenceNumber(byte[] seq_num) {
+        int octet = 7;
+        while (octet >= 0) {
+            seq_num[octet] ++;
+            if (seq_num[octet] == 0) {
+                // characteristic overflow, so
+                // carrying a number in adding
+                octet --;
+            } else {
+                return;
+            }
+        }
+    }
+
+    /**
+     * Shutdownes the protocol. It will be impossiblke to use the instance
+     * after the calling of this method.
+     */
+    protected void shutdown() {
+        encCipher = null;
+        decCipher = null;
+        for (int i=0; i<write_seq_num.length; i++) {
+            write_seq_num[i] = 0;
+            read_seq_num[i] = 0;
+        }
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateSSLv3.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateSSLv3.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateSSLv3.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateSSLv3.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,355 @@
+/*
+ *  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.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLProtocolException;
+
+/**
+ * This class incapsulates the operating environment of the SSL v3
+ * (http://wp.netscape.com/eng/ssl3) Record Protocol and provides 
+ * relating encryption/decryption functionality. 
+ * The work functionality is based on the security
+ * parameters negotiated during the handshake.
+ */
+public class ConnectionStateSSLv3 extends ConnectionState {
+
+    // digest to create and check the message integrity info
+    private final MessageDigest messageDigest;
+    private final byte[] mac_write_secret;
+    private final byte[] mac_read_secret;
+
+    // paddings
+    private final byte[] pad_1;
+    private final byte[] pad_2;
+    // array will hold the part of the MAC material:
+    // length of 3 == 1(SSLCompressed.type) + 2(SSLCompressed.length)
+    // (more on SSLv3 MAC computation and payload protection see
+    // SSL v3 specification, p. 5.2.3)
+    private final byte[] mac_material_part = new byte[3];
+
+    /**
+     * Creates the instance of SSL v3 Connection State. All of the
+     * security parameters are provided by session object.
+     * @param   session: the sessin object which incapsulates
+     * all of the security parameters established by handshake protocol.
+     * The key calculation for the state is done according
+     * to the SSL v3 Protocol specification.
+     * (http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt)
+     */
+    protected ConnectionStateSSLv3(SSLSessionImpl session) {
+        try {
+            CipherSuite cipherSuite = session.cipherSuite;
+
+            boolean is_exportabe =  cipherSuite.isExportable();
+            hash_size = cipherSuite.getMACLength();
+            int key_size = (is_exportabe)
+                ? cipherSuite.keyMaterial
+                : cipherSuite.expandedKeyMaterial;
+            int iv_size = cipherSuite.getBlockSize();
+
+            String algName = cipherSuite.getBulkEncryptionAlgorithm();
+            String hashName = cipherSuite.getHashName();
+            if (logger != null) {
+                logger.println("ConnectionStateSSLv3.create:");
+                logger.println("  cipher suite name: "
+                                        + session.getCipherSuite());
+                logger.println("  encryption alg name: " + algName);
+                logger.println("  hash alg name: " + hashName);
+                logger.println("  hash size: " + hash_size);
+                logger.println("  block size: " + iv_size);
+                logger.println("  IV size (== block size):" + iv_size);
+                logger.println("  key size: " + key_size);
+            }
+
+            byte[] clientRandom = session.clientRandom;
+            byte[] serverRandom = session.serverRandom;
+            // so we need PRF value of size of
+            // 2*hash_size + 2*key_size + 2*iv_size
+            byte[] key_block = new byte[2*hash_size + 2*key_size + 2*iv_size];
+            byte[] seed = new byte[clientRandom.length + serverRandom.length];
+            System.arraycopy(serverRandom, 0, seed, 0, serverRandom.length);
+            System.arraycopy(clientRandom, 0, seed, serverRandom.length,
+                    clientRandom.length);
+
+            PRF.computePRF_SSLv3(key_block, session.master_secret, seed);
+
+            byte[] client_mac_secret = new byte[hash_size];
+            byte[] server_mac_secret = new byte[hash_size];
+            byte[] client_key = new byte[key_size];
+            byte[] server_key = new byte[key_size];
+
+            boolean is_client = !session.isServer;
+
+            is_block_cipher = (iv_size > 0);
+
+            System.arraycopy(key_block, 0, client_mac_secret, 0, hash_size);
+            System.arraycopy(key_block, hash_size,
+                    server_mac_secret, 0, hash_size);
+            System.arraycopy(key_block, 2*hash_size, client_key, 0, key_size);
+            System.arraycopy(key_block, 2*hash_size+key_size,
+                    server_key, 0, key_size);
+
+            IvParameterSpec clientIV = null;
+            IvParameterSpec serverIV = null;
+
+            if (is_exportabe) {
+                if (logger != null) {
+                    logger.println("ConnectionStateSSLv3: is_exportable");
+                }
+
+                MessageDigest md5 = MessageDigest.getInstance("MD5");
+                md5.update(client_key);
+                md5.update(clientRandom);
+                md5.update(serverRandom);
+                client_key = md5.digest();
+
+                md5.update(server_key);
+                md5.update(serverRandom);
+                md5.update(clientRandom);
+                server_key = md5.digest();
+
+                key_size = cipherSuite.expandedKeyMaterial;
+
+                if (is_block_cipher) {
+                    md5.update(clientRandom);
+                    md5.update(serverRandom);
+                    clientIV = new IvParameterSpec(md5.digest(), 0, iv_size);
+                    md5.update(serverRandom);
+                    md5.update(clientRandom);
+                    serverIV = new IvParameterSpec(md5.digest(), 0, iv_size);
+                }
+            } else if (is_block_cipher) {
+                clientIV = new IvParameterSpec(key_block,
+                        2*hash_size+2*key_size, iv_size);
+                serverIV = new IvParameterSpec(key_block,
+                        2*hash_size+2*key_size+iv_size, iv_size);
+            }
+
+            if (logger != null) {
+                logger.println("is exportable: "+is_exportabe);
+                logger.println("master_secret");
+                logger.print(session.master_secret);
+                logger.println("client_random");
+                logger.print(clientRandom);
+                logger.println("server_random");
+                logger.print(serverRandom);
+                //logger.println("key_block");
+                //logger.print(key_block);
+                logger.println("client_mac_secret");
+                logger.print(client_mac_secret);
+                logger.println("server_mac_secret");
+                logger.print(server_mac_secret);
+                logger.println("client_key");
+                logger.print(client_key, 0, key_size);
+                logger.println("server_key");
+                logger.print(server_key, 0, key_size);
+                if (clientIV != null) {
+                    logger.println("client_iv");
+                    logger.print(clientIV.getIV());
+                    logger.println("server_iv");
+                    logger.print(serverIV.getIV());
+                } else {
+                    logger.println("no IV.");
+                }
+            }
+            encCipher = Cipher.getInstance(algName);
+            decCipher = Cipher.getInstance(algName);
+            messageDigest = MessageDigest.getInstance(hashName);
+            if (is_client) { // client side
+                encCipher.init(Cipher.ENCRYPT_MODE,
+                        new SecretKeySpec(client_key, 0, key_size, algName),
+                        clientIV);
+                decCipher.init(Cipher.DECRYPT_MODE,
+                        new SecretKeySpec(server_key, 0, key_size, algName),
+                        serverIV);
+                mac_write_secret = client_mac_secret;
+                mac_read_secret = server_mac_secret;
+            } else { // server side
+                encCipher.init(Cipher.ENCRYPT_MODE,
+                        new SecretKeySpec(server_key, 0, key_size, algName),
+                        serverIV);
+                decCipher.init(Cipher.DECRYPT_MODE,
+                        new SecretKeySpec(client_key, 0, key_size, algName),
+                        clientIV);
+                mac_write_secret = server_mac_secret;
+                mac_read_secret = client_mac_secret;
+            }
+            if (hashName.equals("MD5")) {
+                pad_1 = SSLv3Constants.MD5pad1;
+                pad_2 = SSLv3Constants.MD5pad2;
+            } else {
+                pad_1 = SSLv3Constants.SHApad1;
+                pad_2 = SSLv3Constants.SHApad2;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
+                    new SSLProtocolException(
+                        "Error during computation of security parameters"));
+        }
+    }
+
+    /**
+     * Creates the GenericStreamCipher or GenericBlockCipher
+     * data structure for specified data of specified type.
+     * @throws AlertException if alert was occured.
+     */
+    protected byte[] encrypt(byte type, byte[] fragment, int offset, int len) {
+        try {
+            int content_mac_length = len + hash_size;
+            int padding_length = is_block_cipher
+                    ? padding_length =
+                        ((8 - (++content_mac_length & 0x07)) & 0x07)
+                    : 0;
+            byte[] res = new byte[content_mac_length + padding_length];
+            System.arraycopy(fragment, offset, res, 0, len);
+
+            mac_material_part[0] = type;
+            mac_material_part[1] = (byte) ((0x00FF00 & len) >> 8);
+            mac_material_part[2] = (byte) (0x0000FF & len);
+
+            messageDigest.update(mac_write_secret);
+            messageDigest.update(pad_1);
+            messageDigest.update(write_seq_num);
+            messageDigest.update(mac_material_part);
+            messageDigest.update(fragment, offset, len);
+            byte[] digest = messageDigest.digest();
+            messageDigest.update(mac_write_secret);
+            messageDigest.update(pad_2);
+            messageDigest.update(digest);
+            digest = messageDigest.digest();
+            System.arraycopy(digest, 0, res, len, hash_size);
+
+            //if (logger != null) {
+            //    logger.println("MAC Material:");
+            //    logger.print(write_seq_num);
+            //    logger.print(mac_material_header);
+            //    logger.print(fragment, offset, len);
+            //}
+
+            if (is_block_cipher) {
+                // do padding:
+                Arrays.fill(res, content_mac_length-1,
+                        res.length, (byte) (padding_length));
+            }
+            if (logger != null) {
+                logger.println("SSLRecordProtocol.encrypt: "
+                        + (is_block_cipher
+                            ? "GenericBlockCipher with padding["
+                                +padding_length+"]:"
+                            : "GenericStreamCipher:"));
+                logger.print(res);
+            }
+            byte[] rez = new byte[encCipher.getOutputSize(res.length)];
+            encCipher.update(res, 0, res.length, rez);
+            incSequenceNumber(write_seq_num);
+            return rez;
+        } catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
+                    new SSLProtocolException("Error during the encryption"));
+        }
+    }
+
+    /**
+     * Retrieves the fragment of the Plaintext structure of
+     * the specified type from the provided data.
+     * @throws AlertException if alert was occured.
+     */
+    protected byte[] decrypt(byte type, byte[] fragment,
+            int offset, int len) {
+        // plain data of the Generic[Stream|Block]Cipher structure
+        byte[] data = decCipher.update(fragment, offset, len);
+        // the 'content' part of the structure
+        byte[] content;
+        if (is_block_cipher) {
+            // check padding
+            int padding_length = data[data.length-1];
+            for (int i=0; i<padding_length; i++) {
+                if (data[data.length-2-i] != padding_length) {
+                    throw new AlertException(
+                            AlertProtocol.DECRYPTION_FAILED,
+                            new SSLProtocolException(
+                                "Received message has bad padding"));
+                }
+            }
+            content = new byte[data.length - hash_size - padding_length - 1];
+        } else {
+            content = new byte[data.length - hash_size];
+        }
+
+        byte[] mac_value;
+
+        mac_material_part[0] = type;
+        mac_material_part[1] = (byte) ((0x00FF00 & content.length) >> 8);
+        mac_material_part[2] = (byte) (0x0000FF & content.length);
+
+        messageDigest.update(mac_read_secret);
+        messageDigest.update(pad_1);
+        messageDigest.update(read_seq_num);
+        messageDigest.update(mac_material_part);
+        messageDigest.update(data, 0, content.length);
+        mac_value = messageDigest.digest();
+        messageDigest.update(mac_read_secret);
+        messageDigest.update(pad_2);
+        messageDigest.update(mac_value);
+        mac_value = messageDigest.digest();
+
+        if (logger != null) {
+            logger.println("Decrypted:");
+            logger.print(data);
+            //logger.println("MAC Material:");
+            //logger.print(read_seq_num);
+            //logger.print(mac_material_header);
+            //logger.print(data, 0, content.length);
+            logger.println("Expected mac value:");
+            logger.print(mac_value);
+        }
+        // checking the mac value
+        for (int i=0; i<hash_size; i++) {
+            if (mac_value[i] != data[i+content.length]) {
+                throw new AlertException(AlertProtocol.BAD_RECORD_MAC,
+                        new SSLProtocolException("Bad record MAC"));
+            }
+        }
+        System.arraycopy(data, 0, content, 0, content.length);
+        incSequenceNumber(read_seq_num);
+        return content;
+    }
+
+    /**
+     * Shutdownes the protocol. It will be impossiblke to use the instance
+     * after the calling of this method.
+     */
+    protected void shutdown() {
+        Arrays.fill(mac_write_secret, (byte) 0);
+        Arrays.fill(mac_read_secret, (byte) 0);
+        super.shutdown();
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateTLS.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateTLS.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateTLS.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ConnectionStateTLS.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,349 @@
+/*
+ *  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.GeneralSecurityException;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLProtocolException;
+
+/**
+ * This class incapsulates the operating environment of the TLS v1
+ * (http://www.ietf.org/rfc/rfc2246.txt) Record Protocol and provides 
+ * relating encryption/decryption functionality. 
+ * The work functionality is based on the security
+ * parameters negotiated during the handshake.
+ */
+public class ConnectionStateTLS extends ConnectionState {
+
+    // Precomputed prf label values:
+    // "key expansion".getBytes()
+    private static byte[] KEY_EXPANSION_LABEL = {
+        (byte) 0x6B, (byte) 0x65, (byte) 0x79, (byte) 0x20, (byte) 0x65, 
+        (byte) 0x78, (byte) 0x70, (byte) 0x61, (byte) 0x6E, (byte) 0x73, 
+        (byte) 0x69, (byte) 0x6F, (byte) 0x6E };
+
+    // "client write key".getBytes()
+    private static byte[] CLIENT_WRITE_KEY_LABEL = {
+        (byte) 0x63, (byte) 0x6C, (byte) 0x69, (byte) 0x65, (byte) 0x6E, 
+        (byte) 0x74, (byte) 0x20, (byte) 0x77, (byte) 0x72, (byte) 0x69, 
+        (byte) 0x74, (byte) 0x65, (byte) 0x20, (byte) 0x6B, (byte) 0x65, 
+        (byte) 0x79 };
+
+    // "server write key".getBytes()
+    private static byte[] SERVER_WRITE_KEY_LABEL = {
+        (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76, (byte) 0x65, 
+        (byte) 0x72, (byte) 0x20, (byte) 0x77, (byte) 0x72, (byte) 0x69, 
+        (byte) 0x74, (byte) 0x65, (byte) 0x20, (byte) 0x6B, (byte) 0x65, 
+        (byte) 0x79 };
+
+    // "IV block".getBytes()
+    private static byte[] IV_BLOCK_LABEL = {
+        (byte) 0x49, (byte) 0x56, (byte) 0x20, (byte) 0x62, (byte) 0x6C, 
+        (byte) 0x6F, (byte) 0x63, (byte) 0x6B };
+    
+    // MACs to create and check the message integrity info
+    private final Mac encMac;
+    private final Mac decMac;
+
+    // Once created permanently used array:
+    // is used to create the header of the MAC material value:
+    // 5 == 1(TLSCompressed.type) + 2(TLSCompressed.version) +
+    //      2(TLSCompressed.length)
+    private final byte[] mac_material_header = new byte[] {0, 3, 1, 0, 0};
+
+    /**
+     * Creates the instance of TLS v1 Connection State. All of the
+     * security parameters are provided by session object.
+     * @param   session: the sessin object which incapsulates
+     * all of the security parameters established by handshake protocol.
+     * The key calculation for the state is done according
+     * to the TLS v 1.0 Protocol specification.
+     * (http://www.ietf.org/rfc/rfc2246.txt)
+     */
+    protected ConnectionStateTLS(SSLSessionImpl session) {
+        try {
+            CipherSuite cipherSuite = session.cipherSuite;
+
+            hash_size = cipherSuite.getMACLength();
+            boolean is_exportabe =  cipherSuite.isExportable();
+            int key_size = (is_exportabe)
+                ? cipherSuite.keyMaterial
+                : cipherSuite.expandedKeyMaterial;
+            int iv_size = cipherSuite.getBlockSize();
+
+            String algName = cipherSuite.getBulkEncryptionAlgorithm();
+            String macName = cipherSuite.getHmacName();
+            if (logger != null) {
+                logger.println("ConnectionStateTLS.create:");
+                logger.println("  cipher suite name: "
+                                            + cipherSuite.getName());
+                logger.println("  encryption alg name: " + algName);
+                logger.println("  mac alg name: " + macName);
+                logger.println("  hash size: " + hash_size);
+                logger.println("  block size: " + iv_size);
+                logger.println("  IV size (== block size):" + iv_size);
+                logger.println("  key size: " + key_size);
+            }
+
+            byte[] clientRandom = session.clientRandom;
+            byte[] serverRandom = session.serverRandom;
+            // so we need PRF value of size of
+            // 2*hash_size + 2*key_size + 2*iv_size
+            byte[] key_block = new byte[2*hash_size + 2*key_size + 2*iv_size];
+            byte[] seed = new byte[clientRandom.length + serverRandom.length];
+            System.arraycopy(serverRandom, 0, seed, 0, serverRandom.length);
+            System.arraycopy(clientRandom, 0, seed, serverRandom.length,
+                    clientRandom.length);
+
+            PRF.computePRF(key_block, session.master_secret,
+                    KEY_EXPANSION_LABEL, seed);
+
+            byte[] client_mac_secret = new byte[hash_size];
+            byte[] server_mac_secret = new byte[hash_size];
+            byte[] client_key = new byte[key_size];
+            byte[] server_key = new byte[key_size];
+
+            boolean is_client = !session.isServer;
+
+            is_block_cipher = (iv_size > 0);
+            // do not count, as block_size is always 8
+            // block_size = iv_size;
+
+            System.arraycopy(key_block, 0, client_mac_secret, 0, hash_size);
+            System.arraycopy(key_block, hash_size,
+                    server_mac_secret, 0, hash_size);
+            System.arraycopy(key_block, 2*hash_size, client_key, 0, key_size);
+            System.arraycopy(key_block, 2*hash_size+key_size,
+                    server_key, 0, key_size);
+
+            IvParameterSpec clientIV = null;
+            IvParameterSpec serverIV = null;
+
+            if (is_exportabe) {
+                System.arraycopy(clientRandom, 0,
+                        seed, 0, clientRandom.length);
+                System.arraycopy(serverRandom, 0,
+                        seed, clientRandom.length, serverRandom.length);
+                byte[] final_client_key =
+                    new byte[cipherSuite.expandedKeyMaterial];
+                byte[] final_server_key =
+                    new byte[cipherSuite.expandedKeyMaterial];
+                PRF.computePRF(final_client_key, client_key,
+                        CLIENT_WRITE_KEY_LABEL, seed);
+                PRF.computePRF(final_server_key, server_key,
+                        SERVER_WRITE_KEY_LABEL, seed);
+                client_key = final_client_key;
+                server_key = final_server_key;
+                if (is_block_cipher) {
+                    byte[] iv_block = new byte[2*iv_size];
+                    PRF.computePRF(iv_block, null, IV_BLOCK_LABEL, seed);
+                    clientIV = new IvParameterSpec(iv_block, 0, iv_size);
+                    serverIV = new IvParameterSpec(iv_block, iv_size, iv_size);
+                }
+            } else if (is_block_cipher) {
+                clientIV = new IvParameterSpec(key_block,
+                        2*(hash_size+key_size), iv_size);
+                serverIV = new IvParameterSpec(key_block,
+                        2*(hash_size+key_size)+iv_size, iv_size);
+            }
+
+            if (logger != null) {
+                logger.println("is exportable: "+is_exportabe);
+                logger.println("master_secret");
+                logger.print(session.master_secret);
+                logger.println("client_random");
+                logger.print(clientRandom);
+                logger.println("server_random");
+                logger.print(serverRandom);
+                //logger.println("key_block");
+                //logger.print(key_block);
+                logger.println("client_mac_secret");
+                logger.print(client_mac_secret);
+                logger.println("server_mac_secret");
+                logger.print(server_mac_secret);
+                logger.println("client_key");
+                logger.print(client_key);
+                logger.println("server_key");
+                logger.print(server_key);
+                if (clientIV == null) {
+                    logger.println("no IV.");
+                } else {
+                    logger.println("client_iv");
+                    logger.print(clientIV.getIV());
+                    logger.println("server_iv");
+                    logger.print(serverIV.getIV());
+                }
+            }
+
+            encCipher = Cipher.getInstance(algName);
+            decCipher = Cipher.getInstance(algName);
+            encMac = Mac.getInstance(macName);
+            decMac = Mac.getInstance(macName);
+
+            if (is_client) { // client side
+                encCipher.init(Cipher.ENCRYPT_MODE,
+                        new SecretKeySpec(client_key, algName), clientIV);
+                decCipher.init(Cipher.DECRYPT_MODE,
+                        new SecretKeySpec(server_key, algName), serverIV);
+                encMac.init(new SecretKeySpec(client_mac_secret, macName));
+                decMac.init(new SecretKeySpec(server_mac_secret, macName));
+            } else { // server side
+                encCipher.init(Cipher.ENCRYPT_MODE,
+                        new SecretKeySpec(server_key, algName), serverIV);
+                decCipher.init(Cipher.DECRYPT_MODE,
+                        new SecretKeySpec(client_key, algName), clientIV);
+                encMac.init(new SecretKeySpec(server_mac_secret, macName));
+                decMac.init(new SecretKeySpec(client_mac_secret, macName));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
+                    new SSLProtocolException(
+                        "Error during computation of security parameters"));
+        }
+    }
+
+    /**
+     * Creates the GenericStreamCipher or GenericBlockCipher
+     * data structure for specified data of specified type.
+     * @throws AlertException if alert was occured.
+     */
+    protected byte[] encrypt(byte type, byte[] fragment, int offset, int len) {
+        try {
+            int content_mac_length = len + hash_size;
+            int padding_length = is_block_cipher
+                    ? ((8 - (++content_mac_length & 0x07)) & 0x07)
+                    : 0;
+            byte[] res = new byte[content_mac_length + padding_length];
+            System.arraycopy(fragment, offset, res, 0, len);
+
+            mac_material_header[0] = type;
+            mac_material_header[3] = (byte) ((0x00FF00 & len) >> 8);
+            mac_material_header[4] = (byte) (0x0000FF & len);
+
+            encMac.update(write_seq_num);
+            encMac.update(mac_material_header);
+            encMac.update(fragment, offset, len);
+            encMac.doFinal(res, len);
+
+            //if (logger != null) {
+            //    logger.println("MAC Material:");
+            //    logger.print(write_seq_num);
+            //    logger.print(mac_material_header);
+            //    logger.print(fragment, offset, len);
+            //}
+
+            if (is_block_cipher) {
+                // do padding:
+                Arrays.fill(res, content_mac_length-1,
+                        res.length, (byte) (padding_length));
+            }
+            if (logger != null) {
+                logger.println("SSLRecordProtocol.do_encryption: Generic"
+                        + (is_block_cipher
+                            ? "BlockCipher with padding["+padding_length+"]:"
+                            : "StreamCipher:"));
+                logger.print(res);
+            }
+            byte[] rez = new byte[encCipher.getOutputSize(res.length)];
+            // We should not call just doFinal because it reinitialize
+            // the cipher, but as says rfc 2246:
+            // "For stream ciphers that do not use a synchronization
+            // vector (such as RC4), the stream cipher state from the end
+            // of one record is simply used on the subsequent packet."
+            // and for block ciphers:
+            // "The IV for subsequent records is the last ciphertext block from
+            // the previous record."
+            // i.e. we should keep the cipher state.
+            encCipher.update(res, 0, res.length, rez);
+            incSequenceNumber(write_seq_num);
+            return rez;
+        } catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
+                    new SSLProtocolException("Error during the encryption"));
+        }
+    }
+
+    /**
+     * Retrieves the fragment of the Plaintext structure of
+     * the specified type from the provided data representing
+     * the Generic[Stream|Block]Cipher structure.
+     * @throws AlertException if alert was occured.
+     */
+    protected byte[] decrypt(byte type, byte[] fragment,
+            int offset, int len) {
+        // plain data of the Generic[Stream|Block]Cipher structure
+        byte[] data = decCipher.update(fragment, offset, len);
+        // the 'content' part of the structure
+        byte[] content;
+        if (is_block_cipher) {
+            // check padding
+            int padding_length = data[data.length-1];
+            for (int i=0; i<padding_length; i++) {
+                if (data[data.length-2-i] != padding_length) {
+                    throw new AlertException(
+                            AlertProtocol.DECRYPTION_FAILED,
+                            new SSLProtocolException(
+                                "Received message has bad padding"));
+                }
+            }
+            content = new byte[data.length - hash_size - padding_length - 1];
+        } else {
+            content = new byte[data.length - hash_size];
+        }
+
+        mac_material_header[0] = type;
+        mac_material_header[3] = (byte) ((0x00FF00 & content.length) >> 8);
+        mac_material_header[4] = (byte) (0x0000FF & content.length);
+
+        decMac.update(read_seq_num);
+        decMac.update(mac_material_header);
+        decMac.update(data, 0, content.length); // mac.update(fragment);
+        byte[] mac_value = decMac.doFinal();
+        if (logger != null) {
+            logger.println("Decrypted:");
+            logger.print(data);
+            //logger.println("MAC Material:");
+            //logger.print(read_seq_num);
+            //logger.print(mac_material_header);
+            //logger.print(data, 0, content.length);
+            logger.println("Expected mac value:");
+            logger.print(mac_value);
+        }
+        // checking the mac value
+        for (int i=0; i<hash_size; i++) {
+            if (mac_value[i] != data[i+content.length]) {
+                throw new AlertException(AlertProtocol.BAD_RECORD_MAC,
+                        new SSLProtocolException("Bad record MAC"));
+            }
+        }
+        System.arraycopy(data, 0, content, 0, content.length);
+        incSequenceNumber(read_seq_num);
+        return content;
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ContentType.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ContentType.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ContentType.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/ContentType.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,53 @@
+/*
+ *  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 class incapsulates the constants determining the
+ * types of SSL/TLS record's content data.
+ * Constant values are taken according to the TLS v1 specification
+ * (http://www.ietf.org/rfc/rfc2246.txt).
+ */
+public class ContentType {
+
+    /**
+     * Identifies change cipher spec message
+     */
+    protected static final byte CHANGE_CIPHER_SPEC = 20;
+
+    /**
+     * Identifies alert message
+     */
+    protected static final byte ALERT = 21;
+
+    /**
+     * Identifies handshake message
+     */
+    protected static final byte HANDSHAKE = 22;
+
+    /**
+     * Identifies application data message
+     */
+    protected static final byte APPLICATION_DATA = 23;
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DHParameters.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DHParameters.java?rev=423275&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DHParameters.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/x-net/src/main/java/org/apache/harmony/security/provider/jsse/DHParameters.java Tue Jul 18 15:50:12 2006
@@ -0,0 +1,112 @@
+/*
+ *  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 contains well-known primes
+ */
+public class DHParameters {
+
+    // Well-known 512 bit prime
+    // http://news.hping.org/sci.crypt.archive/2370.html
+    private static byte[] prime512 = new byte[] { (byte) 0xF5, (byte) 0x2A, (byte) 0xFF,
+            (byte) 0x3C, (byte) 0xE1, (byte) 0xB1, (byte) 0x29, (byte) 0x40,
+            (byte) 0x18, (byte) 0x11, (byte) 0x8D, (byte) 0x7C, (byte) 0x84,
+            (byte) 0xA7, (byte) 0x0A, (byte) 0x72, (byte) 0xD6, (byte) 0x86,
+            (byte) 0xC4, (byte) 0x03, (byte) 0x19, (byte) 0xC8, (byte) 0x07,
+            (byte) 0x29, (byte) 0x7A, (byte) 0xCA, (byte) 0x95, (byte) 0x0C,
+            (byte) 0xD9, (byte) 0x96, (byte) 0x9F, (byte) 0xAB, (byte) 0xD0,
+            (byte) 0x0A, (byte) 0x50, (byte) 0x9B, (byte) 0x02, (byte) 0x46,
+            (byte) 0xD3, (byte) 0x08, (byte) 0x3D, (byte) 0x66, (byte) 0xA4,
+            (byte) 0x5D, (byte) 0x41, (byte) 0x9F, (byte) 0x9C, (byte) 0x7C,
+            (byte) 0xBD, (byte) 0x89, (byte) 0x4B, (byte) 0x22, (byte) 0x19,
+            (byte) 0x26, (byte) 0xBA, (byte) 0xAB, (byte) 0xA2, (byte) 0x5E,
+            (byte) 0xC3, (byte) 0x55, (byte) 0xE9, (byte) 0x2A, (byte) 0x05,
+            (byte) 0x5F };
+
+    // Well-Known Group 1: A 768 bit prime rfc 2539
+    // (http://www.ietf.org/rfc/rfc2539.txt?number=2539)
+    private static byte[] primeGroup1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xC9,
+            (byte) 0x0F, (byte) 0xDA, (byte) 0xA2, (byte) 0x21, (byte) 0x68,
+            (byte) 0xC2, (byte) 0x34, (byte) 0xC4, (byte) 0xC6, (byte) 0x62,
+            (byte) 0x8B, (byte) 0x80, (byte) 0xDC, (byte) 0x1C, (byte) 0xD1,
+            (byte) 0x29, (byte) 0x02, (byte) 0x4E, (byte) 0x08, (byte) 0x8A,
+            (byte) 0x67, (byte) 0xCC, (byte) 0x74, (byte) 0x02, (byte) 0x0B,
+            (byte) 0xBE, (byte) 0xA6, (byte) 0x3B, (byte) 0x13, (byte) 0x9B,
+            (byte) 0x22, (byte) 0x51, (byte) 0x4A, (byte) 0x08, (byte) 0x79,
+            (byte) 0x8E, (byte) 0x34, (byte) 0x04, (byte) 0xDD, (byte) 0xEF,
+            (byte) 0x95, (byte) 0x19, (byte) 0xB3, (byte) 0xCD, (byte) 0x3A,
+            (byte) 0x43, (byte) 0x1B, (byte) 0x30, (byte) 0x2B, (byte) 0x0A,
+            (byte) 0x6D, (byte) 0xF2, (byte) 0x5F, (byte) 0x14, (byte) 0x37,
+            (byte) 0x4F, (byte) 0xE1, (byte) 0x35, (byte) 0x6D, (byte) 0x6D,
+            (byte) 0x51, (byte) 0xC2, (byte) 0x45, (byte) 0xE4, (byte) 0x85,
+            (byte) 0xB5, (byte) 0x76, (byte) 0x62, (byte) 0x5E, (byte) 0x7E,
+            (byte) 0xC6, (byte) 0xF4, (byte) 0x4C, (byte) 0x42, (byte) 0xE9,
+            (byte) 0xA6, (byte) 0x3A, (byte) 0x36, (byte) 0x20, (byte) 0xFF,
+            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+            (byte) 0xFF, (byte) 0xFF };
+
+    // Well-Known Group 2: A 1024 bit prime rfc 2539
+    // (http://www.ietf.org/rfc/rfc2539.txt?number=2539)
+    private static byte[] primeGroup2 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xC9,
+            (byte) 0x0F, (byte) 0xDA, (byte) 0xA2, (byte) 0x21, (byte) 0x68,
+            (byte) 0xC2, (byte) 0x34, (byte) 0xC4, (byte) 0xC6, (byte) 0x62,
+            (byte) 0x8B, (byte) 0x80, (byte) 0xDC, (byte) 0x1C, (byte) 0xD1,
+            (byte) 0x29, (byte) 0x02, (byte) 0x4E, (byte) 0x08, (byte) 0x8A,
+            (byte) 0x67, (byte) 0xCC, (byte) 0x74, (byte) 0x02, (byte) 0x0B,
+            (byte) 0xBE, (byte) 0xA6, (byte) 0x3B, (byte) 0x13, (byte) 0x9B,
+            (byte) 0x22, (byte) 0x51, (byte) 0x4A, (byte) 0x08, (byte) 0x79,
+            (byte) 0x8E, (byte) 0x34, (byte) 0x04, (byte) 0xDD, (byte) 0xEF,
+            (byte) 0x95, (byte) 0x19, (byte) 0xB3, (byte) 0xCD, (byte) 0x3A,
+            (byte) 0x43, (byte) 0x1B, (byte) 0x30, (byte) 0x2B, (byte) 0x0A,
+            (byte) 0x6D, (byte) 0xF2, (byte) 0x5F, (byte) 0x14, (byte) 0x37,
+            (byte) 0x4F, (byte) 0xE1, (byte) 0x35, (byte) 0x6D, (byte) 0x6D,
+            (byte) 0x51, (byte) 0xC2, (byte) 0x45, (byte) 0xE4, (byte) 0x85,
+            (byte) 0xB5, (byte) 0x76, (byte) 0x62, (byte) 0x5E, (byte) 0x7E,
+            (byte) 0xC6, (byte) 0xF4, (byte) 0x4C, (byte) 0x42, (byte) 0xE9,
+            (byte) 0xA6, (byte) 0x37, (byte) 0xED, (byte) 0x6B, (byte) 0x0B,
+            (byte) 0xFF, (byte) 0x5C, (byte) 0xB6, (byte) 0xF4, (byte) 0x06,
+            (byte) 0xB7, (byte) 0xED, (byte) 0xEE, (byte) 0x38, (byte) 0x6B,
+            (byte) 0xFB, (byte) 0x5A, (byte) 0x89, (byte) 0x9F, (byte) 0xA5,
+            (byte) 0xAE, (byte) 0x9F, (byte) 0x24, (byte) 0x11, (byte) 0x7C,
+            (byte) 0x4B, (byte) 0x1F, (byte) 0xE6, (byte) 0x49, (byte) 0x28,
+            (byte) 0x66, (byte) 0x51, (byte) 0xEC, (byte) 0xE6, (byte) 0x53,
+            (byte) 0x81, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF
+    };
+    
+    private static byte[] prime;
+    
+    static {
+//TODO set prime depand on some system or security property        
+        prime = prime512;
+    }
+    
+    /**
+     * Returns prime bytes
+     * @return
+     */
+    public static byte[] getPrime() {
+        return prime;
+    }
+}
\ No newline at end of file