/*
 * @(#)MessageDigestSpi.java	1.1 97/10/30
 * 
 * Copyright 1993-1997 Sun Microsystems, Inc. 901 San Antonio Road, 
 * Palo Alto, California, 94303, U.S.A.  All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 * 
 * CopyrightVersion 1.2
 * 
 */

package com.novell.java.security;

import java.util.*;
import java.lang.*;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;

/**
 * Defines the Service Provider Interface (SPI) for the MessageDigest
 * class. The MessageDigest class provides the functionality of a
 * message digest algorithm, such as MD5 or SHA. Message digests are
 * secure one-way hash functions that take arbitrary-sized data and
 * output a fixed-length hash value.
 *
 * <p> All the abstract methods in this class must be implemented by a 
 * cryptographic service provider who wishes to supply the implementation
 * of a particular message digest algorithm. Implementations are free to
 * implement the Cloneable interface.
 *
 * @author Benjamin Renaud 
 *
 * @version 1.1 98/01/14
 *
 * @see MessageDigest
 */

public abstract class MessageDigestSpi {

    /**
     * Returns the message digest length in bytes. This concrete method
     * has been added to this previously-defined abstract class for
     * backwards compatibility (it cannot be abstract).
     *
     * @return The digest length in bytes, but the method may be
     *         overridden by a provider to return the digest length.
     *         The default behavior is to return 0.
     *
     * @since JDK1.2
     */
    protected int engineGetDigestLength() {
	return 0;
    }

    /**
     * Updates the message digest using the specified byte.
     *
     * @param input The byte to use for updating the message digest.
     */
    protected abstract void engineUpdate(byte input);

    /**
     * Updates the message digest using the specified array of bytes,    
     * starting at the specified offset. This should be a no-op if
     * the digest has been finalized.
     *
     * @param input The array of bytes to use for updating the
     *              message digest.
     *
     * @param offset The offset in the array of bytes from which to
     *               start.
     *
     * @param len The number of bytes to use, starting at offset.
     */
    protected abstract void engineUpdate(byte[] input, int offset, int len);

    /**
     * Completes the hash computation by performing final operations
     * such as padding. Once the engineDigest() method has been called,
     * the engine should be reset with the engineReset() method.
     * Resetting is the responsibility of the  engine implementor.
     *
     * @return The array of bytes for the resulting hash value.  
     */
    protected abstract byte[] engineDigest();

    /**
     * Completes the hash computation by performing final operation
     * such as padding. Once the engineDigest() method has been called,
     * the engine should be reset with the engineReset() method.
     * Resetting is the responsibility of the engine implementor.
     *
     * <p>This method should be abstract, but we leave it concrete for
     * binary compatibility.  Knowledgeable providers should override this
     * method. Both this default implementation and the SUN provider do not
     * return partial digests. The presence of the len parameter is solely
     * for consistency in our APIs. If the value of the len parameter is
     * less than the actual digest length, the method will throw a
     * DigestException. The len parameter is ignored if its value is
     * greater than or equal to the actual digest length.
     *
     * @param buf The output buffer in which to store the message
     *            digest.
     *
     * @param offset The offset in the output buffer from which to
     *               start.
     *
     * @param len The number of bytes within the output buffer (buf)
     *            allotted for the digest.
     *
     * @return The length of the message digest stored in the output buffer.
     * 
     * @exception DigestException Thrown if an error occurs.
     *
     * @since JDK1.2
     */
    protected int engineDigest(byte[] buf, int offset, int len)
						throws DigestException {

	byte[] digest = engineDigest();
	if (len < digest.length)
		throw new DigestException("partial digests not returned");
	if (buf.length - offset < digest.length)
		throw new DigestException("insufficient space in the output "
					  + "buffer to store the digest");
	System.arraycopy(digest, 0, buf, offset, digest.length);
	return digest.length;
    }

    /**
     * Resets the digest for further use.
     */
    protected abstract void engineReset();    

    /**    
     * Creates a new message digest object of the same class as
     * this message digest object. It then initializes each of the
     * new object's fields by assigning it the same value as the
     * corresponding field in this object. The clone() method will
     * only clone a message digest object if the implementation is
     * Cloneable. A class indicates that its instances can be
     * cloned by declaring that it implements the Cloneable interface.
     * 
     * @return a clone if the implementation is cloneable.
     *
     * @exception CloneNotSupportedException Thrown if the clone()
     *            method is called on an implementation that does not
     *            support Cloneable.
     */
    public Object clone() throws CloneNotSupportedException {
	if (this instanceof Cloneable) {
	    return super.clone();
	} else {
	    throw new CloneNotSupportedException();
	}
    }
}
