/* 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;
  }
}
