summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-03-27 18:34:52 +0000
committerCasey Marshall <csm@gnu.org>2006-03-27 18:34:52 +0000
commit2c4a3166025fa8bf7ab2ba3c2045c24e898e4dbb (patch)
treea4c8871182ec56c80a8e9770300b0a9f06370143
parent01640c1b8cfacd0ba0e52cfa35d3d0b74ea5403e (diff)
downloadclasspath-2c4a3166025fa8bf7ab2ba3c2045c24e898e4dbb.tar.gz
2006-03-27 Casey Marshall <csm@gnu.org>
* gnu/javax/net/ssl/provider/Record.java (getContentType, getFragment, getFragment, getLength, getVersion): call new accessors. (contentType, fragment, fragment, length, version): new methods. * gnu/javax/net/ssl/provider/CipheredStruct.java, * gnu/javax/net/ssl/provider/GenericBlockCipher.java, * gnu/javax/net/ssl/provider/GenericStreamCipher.java, * gnu/javax/net/ssl/provider/InputSecurityParameters.java, * gnu/javax/net/ssl/provider/OutputSecurityParameters.java: new files. * javax/crypto/Mac.java (update): new method. * javax/crypto/MacSpi.java (engineUpdate): new method.
-rw-r--r--ChangeLog-jessie-nio15
-rw-r--r--gnu/javax/net/ssl/provider/CipheredStruct.java84
-rw-r--r--gnu/javax/net/ssl/provider/GenericBlockCipher.java132
-rw-r--r--gnu/javax/net/ssl/provider/GenericStreamCipher.java88
-rw-r--r--gnu/javax/net/ssl/provider/InputSecurityParameters.java180
-rw-r--r--gnu/javax/net/ssl/provider/OutputSecurityParameters.java188
-rw-r--r--gnu/javax/net/ssl/provider/Record.java41
-rw-r--r--javax/crypto/Mac.java19
-rw-r--r--javax/crypto/MacSpi.java24
9 files changed, 765 insertions, 6 deletions
diff --git a/ChangeLog-jessie-nio b/ChangeLog-jessie-nio
index 0770cc7c0..4a5427ac7 100644
--- a/ChangeLog-jessie-nio
+++ b/ChangeLog-jessie-nio
@@ -1,3 +1,18 @@
+2006-03-27 Casey Marshall <csm@gnu.org>
+
+ * gnu/javax/net/ssl/provider/Record.java
+ (getContentType, getFragment, getFragment, getLength, getVersion):
+ call new accessors.
+ (contentType, fragment, fragment, length, version): new methods.
+ * gnu/javax/net/ssl/provider/CipheredStruct.java,
+ * gnu/javax/net/ssl/provider/GenericBlockCipher.java,
+ * gnu/javax/net/ssl/provider/GenericStreamCipher.java,
+ * gnu/javax/net/ssl/provider/InputSecurityParameters.java,
+ * gnu/javax/net/ssl/provider/OutputSecurityParameters.java: new
+ files.
+ * javax/crypto/Mac.java (update): new method.
+ * javax/crypto/MacSpi.java (engineUpdate): new method.
+
2006-03-26 Casey Marshall <csm@gnu.org>
* jessie-tests/gnu/javax/net/ssl/provider/testAlert.java,
diff --git a/gnu/javax/net/ssl/provider/CipheredStruct.java b/gnu/javax/net/ssl/provider/CipheredStruct.java
new file mode 100644
index 000000000..b0743cea9
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CipheredStruct.java
@@ -0,0 +1,84 @@
+/* CipheredStruct.java -- abstract
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+abstract class CipheredStruct implements Constructed
+{
+ /** The content length. */
+ protected final int length;
+
+ /** The MAC length. */
+ protected final int macLength;
+
+ protected final ByteBuffer buffer;
+
+ protected CipheredStruct (final ByteBuffer buffer, final int length,
+ final int macLength)
+ {
+ this.buffer = buffer;
+ this.length = length;
+ this.macLength = macLength;
+ }
+
+ ByteBuffer content ()
+ {
+ return ((ByteBuffer) buffer.position (0).limit (length)).slice ();
+ }
+
+ int contentLength ()
+ {
+ return length;
+ }
+
+ byte[] mac ()
+ {
+ buffer.position (length);
+ byte[] mac = new byte[macLength];
+ buffer.get (mac);
+ return mac;
+ }
+
+ void setMac (final byte[] mac, final int offset)
+ {
+ buffer.position (length);
+ buffer.put (mac, offset, macLength);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/GenericBlockCipher.java b/gnu/javax/net/ssl/provider/GenericBlockCipher.java
new file mode 100644
index 000000000..3d4c993fb
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/GenericBlockCipher.java
@@ -0,0 +1,132 @@
+/* GenericBlockCipher.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+class GenericBlockCipher extends CipheredStruct
+{
+ GenericBlockCipher (final ByteBuffer buffer, final int length,
+ final int macLength)
+ {
+ super (buffer, length, macLength);
+ }
+
+ GenericBlockCipher (final ByteBuffer buffer, final int macLength)
+ {
+ super (buffer, determineContentLength (buffer, macLength), macLength);
+ }
+
+ private static int determineContentLength (ByteBuffer buffer, int maclen)
+ {
+ int padlen = buffer.get (buffer.limit () - 1) & 0xFF;
+ return buffer.limit () - maclen - padlen - 1;
+ }
+
+ public int getLength ()
+ {
+ return length + macLength + paddingLength () + 1;
+ }
+
+ int paddingLength ()
+ {
+ return buffer.get (buffer.limit () - 1) & 0xFF;
+ }
+
+ void setPaddingLength (final int paddingLength)
+ {
+ buffer.put (length + macLength + paddingLength, (byte) paddingLength);
+ }
+
+ byte[] padding ()
+ {
+ int len = paddingLength ();
+ byte[] pad = new byte[len];
+ buffer.position (length + macLength);
+ buffer.get (pad);
+ return pad;
+ }
+
+ /**
+ * Sets the padding. Note, this assumes that the padding length has
+ * already been set.
+ */
+ void setPadding (final byte[] pad, final int offset)
+ {
+ int len = paddingLength ();
+ buffer.position (length + macLength);
+ buffer.put (pad, offset, len);
+ }
+
+ void setPadding (final byte[] pad)
+ {
+ setPadding (pad, 0);
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.println (" content =");
+ out.println (Util.hexDump (content (),
+ prefix != null ? (prefix + " ") : " "));
+ if (prefix != null) out.print (prefix);
+ out.print (" mac = ");
+ out.println (Util.toHexString (mac (), ':'));
+ if (prefix != null) out.print (prefix);
+ out.print (" padding = ");
+ out.println (Util.toHexString (padding (), ':'));
+ if (prefix != null) out.print (prefix);
+ out.println ("} GenericBlockCipher;");
+
+ return str.toString ();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/GenericStreamCipher.java b/gnu/javax/net/ssl/provider/GenericStreamCipher.java
new file mode 100644
index 000000000..eb7c6f8cc
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/GenericStreamCipher.java
@@ -0,0 +1,88 @@
+/* GenericStreamCipher.java -- a stream-ciphered struct
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+class GenericStreamCipher extends CipheredStruct
+{
+ GenericStreamCipher (final ByteBuffer buffer, final int length,
+ final int macLength)
+ {
+ super (buffer, length, macLength);
+ }
+
+ GenericStreamCipher (final ByteBuffer buffer, final int macLength)
+ {
+ super (buffer, buffer.limit () - macLength, macLength);
+ }
+
+ public int getLength ()
+ {
+ return length + macLength;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.println (" content =");
+ out.println (Util.hexDump (content (),
+ prefix != null ? (prefix + " ") : " "));
+ if (prefix != null) out.print (prefix);
+ out.print (" mac = ");
+ out.println (Util.toHexString (mac (), ':'));
+ if (prefix != null) out.print (prefix);
+ out.println ("} GenericStreamCipher;");
+
+ return str.toString ();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/InputSecurityParameters.java b/gnu/javax/net/ssl/provider/InputSecurityParameters.java
new file mode 100644
index 000000000..ff956652c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/InputSecurityParameters.java
@@ -0,0 +1,180 @@
+/* SecurityParameters.java -- SSL security parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.ShortBufferException;
+
+import javax.net.ssl.SSLException;
+
+class InputSecurityParameters
+{
+ private final Cipher cipher;
+ private final Mac mac;
+ private final Inflater inflater;
+ private final CipherSuite suite;
+ private long sequence;
+
+ InputSecurityParameters (final Cipher cipher, final Mac mac,
+ final Inflater inflater, final CipherSuite suite)
+ {
+ this.cipher = cipher;
+ this.mac = mac;
+ this.inflater = inflater;
+ this.suite = suite;
+ sequence = 0;
+ }
+
+ void decrypt (Record record, ByteBuffer output)
+ throws BadPaddingException, DataFormatException, IllegalBlockSizeException,
+ MacException, SSLException, ShortBufferException
+ {
+ ByteBuffer fragment;
+ if (cipher != null)
+ {
+ ByteBuffer input = record.getFragment ();
+ fragment = ByteBuffer.allocate (input.limit ());
+ cipher.doFinal (input, fragment);
+ }
+ else
+ fragment = record.getFragment ();
+
+ int maclen = 0;
+ if (mac != null)
+ maclen = mac.getMacLength ();
+ CipheredStruct plaintext;
+
+ // We delay throwing an error for bad padding bytes until after we
+ // verify the MAC; this helps avoid timing attacks.
+ boolean badPadding = false;
+
+ if (suite.isStreamCipher ())
+ plaintext = new GenericStreamCipher (fragment, maclen);
+ else
+ {
+ plaintext = new GenericBlockCipher (fragment, maclen);
+ int padlen = ((GenericBlockCipher) plaintext).paddingLength ();
+
+ if (record.version () == ProtocolVersion.SSL_3)
+ {
+ // In SSLv3, the padding length must not be larger than
+ // the cipher's block size.
+ if (padlen > cipher.getBlockSize ())
+ badPadding = true;
+ }
+ else if (record.version () == ProtocolVersion.TLS_1)
+ {
+ // In TLSv1, the padding must be `padlen' copies of the
+ // value `padlen'.
+ byte[] pad = ((GenericBlockCipher) plaintext).padding ();
+ for (int i = 0; i < pad.length; i++)
+ if ((pad[i] & 0xFF) != padlen)
+ badPadding = true;
+ }
+ }
+
+ // Compute and check the MAC.
+ if (mac != null)
+ {
+ mac.update ((byte) (sequence >>> 56));
+ mac.update ((byte) (sequence >>> 48));
+ mac.update ((byte) (sequence >>> 40));
+ mac.update ((byte) (sequence >>> 32));
+ mac.update ((byte) (sequence >>> 24));
+ mac.update ((byte) (sequence >>> 16));
+ mac.update ((byte) (sequence >>> 8));
+ mac.update ((byte) sequence);
+ mac.update ((byte) record.getContentType ().getValue ());
+ ProtocolVersion version = record.version ();
+ if (version != ProtocolVersion.SSL_3)
+ {
+ mac.update ((byte) version.getMajor ());
+ mac.update ((byte) version.getMinor ());
+ }
+ mac.update ((byte) (plaintext.contentLength () >>> 8));
+ mac.update ((byte) plaintext.contentLength ());
+ mac.update (plaintext.content ());
+ byte[] mac1 = mac.doFinal ();
+ byte[] mac2 = plaintext.mac ();
+ if (!Arrays.equals (mac1, mac2))
+ badPadding = true;
+ }
+
+ // We always say "bad MAC" and not "bad padding," because saying
+ // the latter will leak information to an attacker.
+ if (badPadding)
+ throw new MacException ();
+
+ // Inflate the compressed bytes.
+ if (inflater != null)
+ {
+ byte[] inbuffer = new byte[4096];
+ byte[] outbuffer = new byte[4096];
+ boolean done = false;
+ fragment.position (0);
+ while (!done)
+ {
+ int l;
+ if (inflater.needsInput ())
+ {
+ l = Math.min (inbuffer.length, fragment.remaining ());
+ fragment.get (inbuffer, 0, l);
+ inflater.setInput (inbuffer);
+ }
+
+ l = inflater.inflate (outbuffer);
+ output.put (outbuffer, 0, l);
+ done = !fragment.hasRemaining () && inflater.finished ();
+ }
+ }
+ else
+ output.put (plaintext.content ());
+
+ sequence++;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/OutputSecurityParameters.java b/gnu/javax/net/ssl/provider/OutputSecurityParameters.java
new file mode 100644
index 000000000..ed4237b10
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/OutputSecurityParameters.java
@@ -0,0 +1,188 @@
+/* OutputSecurityParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.ShortBufferException;
+
+class OutputSecurityParameters
+{
+ private final Cipher cipher;
+ private final Mac mac;
+ private final Deflater deflater;
+ private final CipherSuite suite;
+ private long sequence;
+
+ OutputSecurityParameters (final Cipher cipher, final Mac mac,
+ final Deflater deflater, final CipherSuite suite)
+ {
+ this.cipher = cipher;
+ this.mac = mac;
+ this.deflater = deflater;
+ this.suite = suite;
+ sequence = 0;
+ }
+
+ int encrypt (final Record record, final ByteBuffer output)
+ throws DataFormatException, IllegalBlockSizeException, ShortBufferException
+ {
+ int macLen = 0;
+ if (mac != null)
+ macLen = mac.getMacLength ();
+
+ int padLen = 0;
+ if (!suite.isStreamCipher ())
+ {
+ padLen = (cipher.getBlockSize() -
+ ((record.length () + macLen + 1) % cipher.getBlockSize()));
+ // For TLSv1 or later, we can use a random amout of padding.
+// if (version != ProtocolVersion.SSL_3 && session.random != null)
+// {
+// padLen += (Math.abs(session.random.nextInt ()) & 7) *
+// outCipher.currentBlockSize();
+// while (padLen > 255)
+// padLen -= outCipher.currentBlockSize();
+// }
+ }
+
+ int fragmentLength = 0;
+ ByteBuffer fragment = null;
+ // Compress the content, if needed.
+ if (deflater != null)
+ {
+ ByteBuffer in = record.fragment ();
+ fragment = ByteBuffer.allocate (record.length () + macLen + padLen + 1024);
+ byte[] inbuf = new byte[4096];
+ byte[] outbuf = new byte[4096];
+
+ in.position (0);
+ while (in.hasRemaining ())
+ {
+ int l = Math.min (in.remaining (), inbuf.length);
+ in.get (inbuf, 0, l);
+ deflater.setInput (inbuf, 0, l);
+ if (!in.hasRemaining ())
+ deflater.finish ();
+ l = deflater.deflate (outbuf);
+ fragment.put (outbuf, 0, l);
+ }
+ fragmentLength = deflater.getTotalOut () + macLen + padLen;
+ fragment = ((ByteBuffer) fragment.position (0).limit (fragmentLength)).slice ();
+ }
+ else
+ {
+ fragmentLength = record.length () + macLen + padLen;
+ fragment = ByteBuffer.allocate (fragmentLength);
+ fragment.put (record.fragment ());
+ }
+
+ CipheredStruct plaintext = null;
+ if (suite.isStreamCipher ())
+ plaintext = new GenericStreamCipher (fragment, fragmentLength - macLen - padLen,
+ macLen);
+ else
+ plaintext = new GenericBlockCipher (fragment, fragmentLength - macLen - padLen,
+ macLen);
+
+ // If there is a MAC, compute it.
+ if (mac != null)
+ {
+ mac.update ((byte) (sequence >>> 56));
+ mac.update ((byte) (sequence >>> 48));
+ mac.update ((byte) (sequence >>> 40));
+ mac.update ((byte) (sequence >>> 32));
+ mac.update ((byte) (sequence >>> 24));
+ mac.update ((byte) (sequence >>> 16));
+ mac.update ((byte) (sequence >>> 8));
+ mac.update ((byte) sequence);
+ mac.update ((byte) record.getContentType ().getValue ());
+ ProtocolVersion version = record.version ();
+ if (version != ProtocolVersion.SSL_3)
+ {
+ mac.update ((byte) version.getMajor ());
+ mac.update ((byte) version.getMinor ());
+ }
+ mac.update ((byte) (plaintext.contentLength () >>> 8));
+ mac.update ((byte) plaintext.contentLength ());
+ mac.update (plaintext.content ());
+ plaintext.setMac (mac.doFinal (), 0);
+ }
+
+ Record outrecord = new Record (output);
+ outrecord.setContentType (record.contentType ());
+ outrecord.setVersion (record.getVersion ());
+ outrecord.setLength (fragmentLength);
+
+ if (cipher != null)
+ {
+ if (padLen > 0)
+ {
+ int x = padLen - 1;
+ byte[] padding = new byte[x];
+ for (int i = 0; i < padding.length; i++)
+ padding[i] = (byte) x;
+ ((GenericBlockCipher) plaintext).setPaddingLength (x);
+ ((GenericBlockCipher) plaintext).setPadding (padding);
+ }
+
+ try
+ {
+ cipher.doFinal (fragment, outrecord.fragment ());
+ }
+ catch (BadPaddingException bpe)
+ {
+ throw new RuntimeException ("caught BadPaddingException; this should not happen", bpe);
+ }
+ }
+ else
+ outrecord.fragment ().put (fragment);
+
+ sequence++;
+
+ return fragmentLength + 5;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/Record.java b/gnu/javax/net/ssl/provider/Record.java
index adbd5cb05..26fbec0c3 100644
--- a/gnu/javax/net/ssl/provider/Record.java
+++ b/gnu/javax/net/ssl/provider/Record.java
@@ -64,29 +64,47 @@ class Record
this.buffer = buffer;
}
+ // XXX remove
+ ContentType getContentType ()
+ {
+ return contentType ();
+ }
+
/**
* Gets the content type field.
*
* @return The content type field.
*/
- ContentType getContentType ()
+ ContentType contentType ()
{
return ContentType.forInteger (buffer.get (0) & 0xFF);
}
+ // XXX remove.
+ int getFragment (final ByteBuffer sink)
+ {
+ return fragment (sink);
+ }
+
/**
* Get the fragment content, storing it into <code>sink</code>.
*
* @param sink The sink for the fragment bytes.
* @return The number of bytes put into <code>sink</code>
*/
- int getFragment (final ByteBuffer sink)
+ int fragment (final ByteBuffer sink)
{
- int length = getLength ();
+ int length = length ();
sink.put (((ByteBuffer) buffer.limit (5 + length).position (5)).slice ());
return length;
}
+ // XXX remove.
+ ByteBuffer getFragment ()
+ {
+ return fragment ();
+ }
+
/**
* Returns the fragment field as a ByteBuffer. The returned buffer
* is shared with this object's underlying buffer, so it will share
@@ -95,28 +113,39 @@ class Record
*
* @return The fragment buffer.
*/
- ByteBuffer getFragment ()
+ ByteBuffer fragment ()
{
int length = getLength ();
return ((ByteBuffer) buffer.limit (5 + length).position (5)).slice ();
}
+ // XXX remove.
+ int getLength ()
+ {
+ return length ();
+ }
+
/**
* Gets the fragment length.
*
* @return The fragment length.
*/
- int getLength ()
+ int length ()
{
return buffer.getShort (3) & 0xFFFF;
}
+ ProtocolVersion getVersion ()
+ {
+ return version ();
+ }
+
/**
* Gets the protocol version field.
*
* @return The protocol version field.
*/
- ProtocolVersion getVersion ()
+ ProtocolVersion version ()
{
int major = buffer.get (1) & 0xFF;
int minor = buffer.get (2) & 0xFF;
diff --git a/javax/crypto/Mac.java b/javax/crypto/Mac.java
index abbff8b23..e0468a786 100644
--- a/javax/crypto/Mac.java
+++ b/javax/crypto/Mac.java
@@ -41,6 +41,7 @@ package javax.crypto;
import gnu.java.security.Engine;
import java.lang.reflect.InvocationTargetException;
+import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -398,6 +399,24 @@ public class Mac implements Cloneable
}
/**
+ * Updates this MAC with the <code>remaining()</input> bytes from
+ * the given byte buffer, starting at <code>position()</code>.
+ *
+ * @param input The input bytes.
+ * @throws IllegalStateException If this instance has not been
+ * initialized.
+ */
+ public final void update (ByteBuffer input)
+ throws IllegalStateException
+ {
+ if (virgin)
+ {
+ throw new IllegalStateException ("not initialized");
+ }
+ macSpi.engineUpdate (input);
+ }
+
+ /**
* Clone this instance, if the underlying implementation supports it.
*
* @return A clone of this instance.
diff --git a/javax/crypto/MacSpi.java b/javax/crypto/MacSpi.java
index b0f96bff3..ec26664f4 100644
--- a/javax/crypto/MacSpi.java
+++ b/javax/crypto/MacSpi.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.crypto;
+import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -142,4 +143,27 @@ public abstract class MacSpi
* @param length The number of bytes to update.
*/
protected abstract void engineUpdate(byte[] input, int offset, int length);
+
+ /**
+ * Update this MAC with a byte buffer.
+ *
+ * <p>Note that the default implementation uses a byte array to
+ * repeatedly <code>get</code> bytes from the buffer, then passes
+ * that byte array to {@link
+ * engineUpdate(byte[],int,int)}. Subclasses are encouraged to
+ * override this implementation if they can operate more efficiently
+ * on byte buffers.
+ *
+ * @param input The input buffer.
+ */
+ protected void engineUpdate (ByteBuffer input)
+ {
+ byte[] buf = new byte[256];
+ while (input.hasRemaining ())
+ {
+ int l = Math.min (input.remaining (), 256);
+ input.get (buf, 0, l);
+ engineUpdate (buf, 0, l);
+ }
+ }
}