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));
+ }
+}