/* 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 <i>UMAC</i> (Universal Message Authentication
 * Code).
 * <p>
 * The <i>UMAC</i> algorithms described are <i>parameterized</i>. 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 <i>UMAC</i> (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
 * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based
 * on experimentation and provide good performance on a wide variety of
 * processors. <i>UMAC16</i> 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 <i>UMAC32</i> is designed to do well on
 * processors with good 32- and 64- bit support. <i>UMAC32</i> may take
 * advantage of SIMD parallelism in future processors.
 * <p>
 * <i>UMAC</i> has been designed to allow implementations which accommodate
 * <i>on-line</i> authentication. This means that pieces of the message may be
 * presented to <i>UMAC</i> 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.
 * <p>
 * To authenticate a message, <code>Msg</code>, 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
 * <pre>
 *     AuthTag = f(Nonce) xor h(Msg)
 * </pre>
 * <p>
 * Here <code>f</code> 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 <i>UMAC</i>, a shared key is used to key the pseudorandom
 * function <code>f</code>, and then <code>f</code> is used for both tag
 * generation and internally to generate all of the bits needed by the universal
 * hash function.
 * <p>
 * The universal hash function that we use is called <code>UHASH</code>. 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.
 * <p>
 * For the pseudorandom function we use the block cipher of the <i>Advanced
 * Encryption Standard</i> (AES).
 * <p>
 * The UMAC32 parameters, considered in this implementation are:
 * <pre>
 *                                    UMAC32
 *                                    ------
 *         WORD-LEN                        4
 *         UMAC-OUTPUT-LEN                 8
 *         L1-KEY-LEN                   1024
 *         UMAC-KEY-LEN                   16
 *         ENDIAN-FAVORITE               BIG *
 *         L1-OPERATIONS-SIGN       UNSIGNED
 * </pre>
 * <p>
 * Please note that this UMAC32 differs from the one described in the paper by
 * the <i>ENDIAN-FAVORITE</i> value.
 * <p>
 * References:
 * <ol>
 * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
 * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
 * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
 * </ol>
 */
public class UMac32
    extends BaseMac
{
  /**
   * Property name of the user-supplied <i>Nonce</i>. 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 <i>UMAC</i> instance consists of defining values for the
   * following parameters:
   * <ol>
   * <li>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}.</li>
   * <li>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).</li>
   * </ol>
   * <p>
   * For convenience, this implementation accepts that not both parameters be
   * always specified.
   * <ul>
   * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i>
   * is not, then this implementation, re-uses the previously set <i>Nonce
   * Material</i> after (a) converting the bytes to an unsigned integer, (b)
   * incrementing the number by one, and (c) converting it back to 16 bytes.</li>
   * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i>
   * is not, then this implementation re-uses the previously set <i>Key Material</i>.
   * </li>
   * </ul>
   * <p>
   * This method throws an exception if no <i>Key Material</i> is specified in
   * the input map, and there is no previously set/defined <i>Key Material</i>
   * (from an earlier invocation of this method). If a <i>Key Material</i> can
   * be used, but no <i>Nonce Material</i> 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;
  }
}
