From 2c4a3166025fa8bf7ab2ba3c2045c24e898e4dbb Mon Sep 17 00:00:00 2001 From: Casey Marshall Date: Mon, 27 Mar 2006 18:34:52 +0000 Subject: 2006-03-27 Casey Marshall * 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. --- ChangeLog-jessie-nio | 15 ++ gnu/javax/net/ssl/provider/CipheredStruct.java | 84 +++++++++ gnu/javax/net/ssl/provider/GenericBlockCipher.java | 132 +++++++++++++++ .../net/ssl/provider/GenericStreamCipher.java | 88 ++++++++++ .../net/ssl/provider/InputSecurityParameters.java | 180 ++++++++++++++++++++ .../net/ssl/provider/OutputSecurityParameters.java | 188 +++++++++++++++++++++ gnu/javax/net/ssl/provider/Record.java | 41 ++++- javax/crypto/Mac.java | 19 +++ javax/crypto/MacSpi.java | 24 +++ 9 files changed, 765 insertions(+), 6 deletions(-) create mode 100644 gnu/javax/net/ssl/provider/CipheredStruct.java create mode 100644 gnu/javax/net/ssl/provider/GenericBlockCipher.java create mode 100644 gnu/javax/net/ssl/provider/GenericStreamCipher.java create mode 100644 gnu/javax/net/ssl/provider/InputSecurityParameters.java create mode 100644 gnu/javax/net/ssl/provider/OutputSecurityParameters.java 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 + + * 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 * 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 sink. * * @param sink The sink for the fragment bytes. * @return The number of bytes put into sink */ - 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; @@ -397,6 +398,24 @@ public class Mac implements Cloneable macSpi.engineUpdate(input, offset, length); } + /** + * Updates this MAC with the remaining() bytes from + * the given byte buffer, starting at position(). + * + * @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. * 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. + * + *

Note that the default implementation uses a byte array to + * repeatedly get 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); + } + } } -- cgit v1.2.1