From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libjava/classpath/gnu/javax/crypto/mac/UMac32.java | 418 +++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 libjava/classpath/gnu/javax/crypto/mac/UMac32.java (limited to 'libjava/classpath/gnu/javax/crypto/mac/UMac32.java') diff --git a/libjava/classpath/gnu/javax/crypto/mac/UMac32.java b/libjava/classpath/gnu/javax/crypto/mac/UMac32.java new file mode 100644 index 000000000..6f53424ea --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/mac/UMac32.java @@ -0,0 +1,418 @@ +/* UMac32.java -- + Copyright (C) 2001, 2002, 2003, 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.crypto.mac; + +import gnu.java.security.Registry; +import gnu.java.security.prng.IRandom; +import gnu.java.security.prng.LimitReachedException; +import gnu.java.security.util.Util; +import gnu.javax.crypto.cipher.CipherFactory; +import gnu.javax.crypto.cipher.IBlockCipher; +import gnu.javax.crypto.prng.UMacGenerator; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.util.HashMap; +import java.util.Map; + +/** + * The implementation of the UMAC (Universal Message Authentication + * Code). + *

+ * The UMAC algorithms described are parameterized. This means + * that various low-level choices, like the endian convention and the underlying + * cryptographic primitive, have not been fixed. One must choose values for + * these parameters before the authentication tag generated by UMAC (for + * a given message, key, and nonce) becomes fully-defined. In this document we + * provide two collections of parameter settings, and have named the sets + * UMAC16 and UMAC32. The parameter sets have been chosen based + * on experimentation and provide good performance on a wide variety of + * processors. UMAC16 is designed to excel on processors which provide + * small-scale SIMD parallelism of the type found in Intel's MMX and Motorola's + * AltiVec instruction sets, while UMAC32 is designed to do well on + * processors with good 32- and 64- bit support. UMAC32 may take + * advantage of SIMD parallelism in future processors. + *

+ * UMAC has been designed to allow implementations which accommodate + * on-line authentication. This means that pieces of the message may be + * presented to UMAC at different times (but in correct order) and an + * on-line implementation will be able to process the message correctly without + * the need to buffer more than a few dozen bytes of the message. For + * simplicity, the algorithms in this specification are presented as if the + * entire message being authenticated were available at once. + *

+ * To authenticate a message, Msg, one first applies the + * universal hash function, resulting in a string which is typically much + * shorter than the original message. The pseudorandom function is applied to a + * nonce, and the result is used in the manner of a Vernam cipher: the + * authentication tag is the xor of the output from the hash function and the + * output from the pseudorandom function. Thus, an authentication tag is + * generated as + *

+ *     AuthTag = f(Nonce) xor h(Msg)
+ * 
+ *

+ * Here f is the pseudorandom function shared between the sender + * and the receiver, and h is a universal hash function shared by the sender and + * the receiver. In UMAC, a shared key is used to key the pseudorandom + * function f, and then f is used for both tag + * generation and internally to generate all of the bits needed by the universal + * hash function. + *

+ * The universal hash function that we use is called UHASH. It + * combines several software-optimized algorithms into a multi-layered + * structure. The algorithm is moderately complex. Some of this complexity comes + * from extensive speed optimizations. + *

+ * For the pseudorandom function we use the block cipher of the Advanced + * Encryption Standard (AES). + *

+ * The UMAC32 parameters, considered in this implementation are: + *

+ *                                    UMAC32
+ *                                    ------
+ *         WORD-LEN                        4
+ *         UMAC-OUTPUT-LEN                 8
+ *         L1-KEY-LEN                   1024
+ *         UMAC-KEY-LEN                   16
+ *         ENDIAN-FAVORITE               BIG *
+ *         L1-OPERATIONS-SIGN       UNSIGNED
+ * 
+ *

+ * Please note that this UMAC32 differs from the one described in the paper by + * the ENDIAN-FAVORITE value. + *

+ * References: + *

    + *
  1. + * UMAC: Message Authentication Code using Universal Hashing.
    + * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.
  2. + *
+ */ +public class UMac32 + extends BaseMac +{ + /** + * Property name of the user-supplied Nonce. The value associated to + * this property name is taken to be a byte array. + */ + public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material"; + /** Known test vector. */ + // private static final String TV1 = "3E5A0E09198B0F94"; + // private static final String TV1 = "5FD764A6D3A9FD9D"; + // private static final String TV1 = "48658DE1D9A70304"; + private static final String TV1 = "455ED214A6909F20"; + private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8); + // UMAC32 parameters + static final int OUTPUT_LEN = 8; + static final int L1_KEY_LEN = 1024; + static final int KEY_LEN = 16; + /** caches the result of the correctness test, once executed. */ + private static Boolean valid; + private byte[] nonce; + private UHash32 uhash32; + private BigInteger nonceReuseCount; + /** The authentication key for this instance. */ + private transient byte[] K; + + /** Trivial 0-arguments constructor. */ + public UMac32() + { + super("umac32"); + } + + /** + * Private constructor for cloning purposes. + * + * @param that the instance to clone. + */ + private UMac32(UMac32 that) + { + this(); + + if (that.K != null) + this.K = (byte[]) that.K.clone(); + if (that.nonce != null) + this.nonce = (byte[]) that.nonce.clone(); + if (that.uhash32 != null) + this.uhash32 = (UHash32) that.uhash32.clone(); + this.nonceReuseCount = that.nonceReuseCount; + } + + public Object clone() + { + return new UMac32(this); + } + + public int macSize() + { + return OUTPUT_LEN; + } + + /** + * Initialising a UMAC instance consists of defining values for the + * following parameters: + *
    + *
  1. Key Material: as the value of the attribute entry keyed by + * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array + * containing the user-specified key material. The length of this array, + * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.
  2. + *
  3. Nonce Material: as the value of the attribute entry keyed by + * {@link #NONCE_MATERIAL}. The value is taken to be a byte array containing + * the user-specified nonce material. The length of this array, if/when + * defined SHOULD be (a) greater than zero, and (b) less or equal to 16 (the + * size of the AES block).
  4. + *
+ *

+ * For convenience, this implementation accepts that not both parameters be + * always specified. + *

+ *

+ * This method throws an exception if no Key Material is specified in + * the input map, and there is no previously set/defined Key Material + * (from an earlier invocation of this method). If a Key Material can + * be used, but no Nonce Material is defined or previously + * set/defined, then a default value of all-zeroes shall be used. + * + * @param attributes one or both of required parameters. + * @throws InvalidKeyException the key material specified is not of the + * correct length. + */ + public void init(Map attributes) throws InvalidKeyException, + IllegalStateException + { + byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL); + byte[] n = (byte[]) attributes.get(NONCE_MATERIAL); + boolean newKey = (key != null); + boolean newNonce = (n != null); + if (newKey) + { + if (key.length != KEY_LEN) + throw new InvalidKeyException("Key length: " + + String.valueOf(key.length)); + K = key; + } + else + { + if (K == null) + throw new InvalidKeyException("Null Key"); + } + if (newNonce) + { + if (n.length < 1 || n.length > 16) + throw new IllegalArgumentException("Invalid Nonce length: " + + String.valueOf(n.length)); + if (n.length < 16) // pad with zeroes + { + byte[] newN = new byte[16]; + System.arraycopy(n, 0, newN, 0, n.length); + nonce = newN; + } + else + nonce = n; + + nonceReuseCount = BigInteger.ZERO; + } + else if (nonce == null) // use all-0 nonce if 1st time + { + nonce = new byte[16]; + nonceReuseCount = BigInteger.ZERO; + } + else if (! newKey) // increment nonce if still below max count + { + nonceReuseCount = nonceReuseCount.add(BigInteger.ONE); + if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0) + { + // limit reached. we SHOULD have a key + throw new InvalidKeyException("Null Key and unusable old Nonce"); + } + BigInteger N = new BigInteger(1, nonce); + N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS); + n = N.toByteArray(); + if (n.length == 16) + nonce = n; + else if (n.length < 16) + { + nonce = new byte[16]; + System.arraycopy(n, 0, nonce, 16 - n.length, n.length); + } + else + { + nonce = new byte[16]; + System.arraycopy(n, n.length - 16, nonce, 0, 16); + } + } + else // do nothing, re-use old nonce value + nonceReuseCount = BigInteger.ZERO; + + if (uhash32 == null) + uhash32 = new UHash32(); + + Map map = new HashMap(); + map.put(MAC_KEY_MATERIAL, K); + uhash32.init(map); + } + + public void update(byte b) + { + uhash32.update(b); + } + + public void update(byte[] b, int offset, int len) + { + uhash32.update(b, offset, len); + } + + public byte[] digest() + { + byte[] result = uhash32.digest(); + byte[] pad = pdf(); // pdf(K, nonce); + for (int i = 0; i < OUTPUT_LEN; i++) + result[i] = (byte)(result[i] ^ pad[i]); + + return result; + } + + public void reset() + { + if (uhash32 != null) + uhash32.reset(); + } + + public boolean selfTest() + { + if (valid == null) + { + byte[] key; + try + { + key = "abcdefghijklmnop".getBytes("ASCII"); + } + catch (UnsupportedEncodingException x) + { + throw new RuntimeException("ASCII not supported"); + } + byte[] nonce = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; + UMac32 mac = new UMac32(); + Map attributes = new HashMap(); + attributes.put(MAC_KEY_MATERIAL, key); + attributes.put(NONCE_MATERIAL, nonce); + try + { + mac.init(attributes); + } + catch (InvalidKeyException x) + { + x.printStackTrace(System.err); + return false; + } + byte[] data = new byte[128]; + data[0] = (byte) 0x80; + mac.update(data, 0, 128); + byte[] result = mac.digest(); + valid = Boolean.valueOf(TV1.equals(Util.toString(result))); + } + return valid.booleanValue(); + } + + /** + * @return byte array of length 8 (or OUTPUT_LEN) bytes. + */ + private byte[] pdf() + { + // Make Nonce 16 bytes by prepending zeroes. done (see init()) + // one AES invocation is enough for more than one PDF invocation + // number of index bits needed = 1 + // Extract index bits and zero low bits of Nonce + BigInteger Nonce = new BigInteger(1, nonce); + int nlowbitsnum = Nonce.testBit(0) ? 1 : 0; + Nonce = Nonce.clearBit(0); + // Generate subkey, AES and extract indexed substring + IRandom kdf = new UMacGenerator(); + Map map = new HashMap(); + map.put(IBlockCipher.KEY_MATERIAL, K); + map.put(UMacGenerator.INDEX, Integer.valueOf(128)); + kdf.init(map); + byte[] Kp = new byte[KEY_LEN]; + try + { + kdf.nextBytes(Kp, 0, KEY_LEN); + } + catch (IllegalStateException x) + { + x.printStackTrace(System.err); + throw new RuntimeException(String.valueOf(x)); + } + catch (LimitReachedException x) + { + x.printStackTrace(System.err); + throw new RuntimeException(String.valueOf(x)); + } + IBlockCipher aes = CipherFactory.getInstance(Registry.AES_CIPHER); + map.put(IBlockCipher.KEY_MATERIAL, Kp); + try + { + aes.init(map); + } + catch (InvalidKeyException x) + { + x.printStackTrace(System.err); + throw new RuntimeException(String.valueOf(x)); + } + catch (IllegalStateException x) + { + x.printStackTrace(System.err); + throw new RuntimeException(String.valueOf(x)); + } + byte[] T = new byte[16]; + aes.encryptBlock(nonce, 0, T, 0); + byte[] result = new byte[OUTPUT_LEN]; + System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN); + return result; + } +} -- cgit v1.2.3