/*
 * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


package sun.security.ssl;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import java.nio.ByteBuffer;

import javax.crypto.Mac;
import javax.crypto.SecretKey;

import sun.security.ssl.CipherSuite.MacAlg;
import static sun.security.ssl.CipherSuite.*;

/**
 * This class computes the "Message Authentication Code" (MAC) for each
 * SSL message.  This is essentially a shared-secret signature, used to
 * provide integrity protection for SSL messages.  The MAC is actually
 * one of several keyed hashes, as associated with the cipher suite and
 * protocol version.  (SSL v3.0 uses one construct, TLS uses another.)
 *
 * <P>NOTE: MAC computation is the only place in the SSL protocol that the
 * sequence number is used.  It's also reset to zero with each change of
 * a cipher spec, so this is the only place this state is needed.
 *
 * @author David Brownell
 * @author Andreas Sterbenz
 */
final class MAC {

    final static MAC NULL = new MAC();

    // Value of the null MAC is fixed
    private static final byte nullMAC[] = new byte[0];

    // internal identifier for the MAC algorithm
    private final MacAlg        macAlg;

    // stuff defined by the kind of MAC algorithm
    private final int           macSize;

    // JCE Mac object
    private final Mac mac;

    // byte array containing the additional information we MAC in each record
    // (see below)
    private final byte[] block;

    // sequence number + record type + + record length
    private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;

    // sequence number + record type + protocol version + record length
    private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;

    // offset of record type in block
    private static final int BLOCK_OFFSET_TYPE    = 8;

    // offset of protocol version number in block (TLS only)
    private static final int BLOCK_OFFSET_VERSION = 8 + 1;

    private MAC() {
        macSize = 0;
        macAlg = M_NULL;
        mac = null;
        block = null;
    }

    /**
     * Set up, configured for the given SSL/TLS MAC type and version.
     */
    MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
            throws NoSuchAlgorithmException, InvalidKeyException {
        this.macAlg = macAlg;
        this.macSize = macAlg.size;

        String algorithm;
        boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);

        if (macAlg == M_MD5) {
            algorithm = tls ? "HmacMD5" : "SslMacMD5";
        } else if (macAlg == M_SHA) {
            algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
        } else {
            throw new RuntimeException("Unknown Mac " + macAlg);
        }

        mac = JsseJce.getMac(algorithm);
        mac.init(key);

        if (tls) {
            block = new byte[BLOCK_SIZE_TLS];
            block[BLOCK_OFFSET_VERSION]   = protocolVersion.major;
            block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
        } else {
            block = new byte[BLOCK_SIZE_SSL];
        }
    }

    /**
     * Returns the length of the MAC.
     */
    int MAClen() {
        return macSize;
    }

    /**
     * Computes and returns the MAC for the data in this byte array.
     *
     * @param type record type
     * @param buf compressed record on which the MAC is computed
     * @param offset start of compressed record data
     * @param len the size of the compressed record
     */
    final byte[] compute(byte type, byte buf[], int offset, int len) {
        return compute(type, null, buf, offset, len);
    }

    /**
     * Compute and returns the MAC for the remaining data
     * in this ByteBuffer.
     *
     * On return, the bb position == limit, and limit will
     * have not changed.
     *
     * @param type record type
     * @param bb a ByteBuffer in which the position and limit
     *          demarcate the data to be MAC'd.
     */
    final byte[] compute(byte type, ByteBuffer bb) {
        return compute(type, bb, null, 0, bb.remaining());
    }

    // increment the sequence number in the block array
    // it is a 64-bit number stored in big-endian format
    private void incrementSequenceNumber() {
        int k = 7;
        while ((k >= 0) && (++block[k] == 0)) {
            k--;
        }
    }

    /*
     * Compute based on either buffer type, either bb.position/limit
     * or buf/offset/len.
     */
    private byte[] compute(byte type, ByteBuffer bb, byte[] buf, int offset, int len) {

        if (macSize == 0) {
            return nullMAC;
        }

        block[BLOCK_OFFSET_TYPE] = type;
        block[block.length - 2]  = (byte)(len >> 8);
        block[block.length - 1]  = (byte)(len     );

        mac.update(block);
        incrementSequenceNumber();

        // content
        if (bb != null) {
            mac.update(bb);
        } else {
            mac.update(buf, offset, len);
        }

        return mac.doFinal();
    }

}
