/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.security;

import java.nio.ByteBuffer;
import java.security.spec.AlgorithmParameterSpec;

/**
 * {@code SignatureSpi} is the <i>Service Provider Interface</i> (<b>SPI</b>)
 * definition for {@link Signature}.
 *
 * @see Signature
 */
public abstract class SignatureSpi {

    /**
     * Implementation specific source of randomness.
     */
    protected SecureRandom appRandom;

    /**
     * Initializes this {@code SignatureSpi} instance for signature
     * verification, using the public key of the identity whose signature is
     * going to be verified.
     *
     * @param publicKey
     *            the public key.
     * @throws InvalidKeyException
     *             if {@code publicKey} is not valid.
     */
    protected abstract void engineInitVerify(PublicKey publicKey)
            throws InvalidKeyException;

    /**
     * Initializes this {@code SignatureSpi} instance for signing, using the
     * private key of the identity whose signature is going to be generated.
     *
     * @param privateKey
     *            the private key.
     * @throws InvalidKeyException
     *             if {@code privateKey} is not valid.
     */
    protected abstract void engineInitSign(PrivateKey privateKey)
            throws InvalidKeyException;

    /**
     * Initializes this {@code SignatureSpi} instance for signing, using the
     * private key of the identity whose signature is going to be generated and
     * the specified source of randomness.
     *
     * @param privateKey
     *            the private key.
     * @param random
     *            the {@code SecureRandom} to use.
     * @throws InvalidKeyException
     *             if {@code privateKey} is not valid.
     */
    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
            throws InvalidKeyException {
        appRandom = random;
        engineInitSign(privateKey);
    }

    /**
     * Updates the data to be verified or to be signed, using the specified
     * {@code byte}.
     *
     * @param b
     *            the byte to update with.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     */
    protected abstract void engineUpdate(byte b) throws SignatureException;

    /**
     * Updates the data to be verified or to be signed, using the given {@code
     * byte[]}, starting form the specified index for the specified length.
     *
     * @param b
     *            the byte array to update with.
     * @param off
     *            the start index in {@code b} of the data.
     * @param len
     *            the number of bytes to use.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     */
    protected abstract void engineUpdate(byte[] b, int off, int len)
            throws SignatureException;

    /**
     * Updates the data to be verified or to be signed, using the specified
     * {@code ByteBuffer}.
     *
     * @param input
     *            the {@code ByteBuffer} to update with.
     * @throws RuntimeException
     *             since {@code SignatureException} is not specified for this
     *             method it throws a {@code RuntimeException} if underlying
     *             {@link #engineUpdate(byte[], int, int)} throws {@code
     *             SignatureException}.
     */
    protected void engineUpdate(ByteBuffer input) {
        if (!input.hasRemaining()) {
            return;
        }
        byte[] tmp;
        if (input.hasArray()) {
            tmp = input.array();
            int offset = input.arrayOffset();
            int position = input.position();
            int limit = input.limit();
            try {
                engineUpdate(tmp, offset + position, limit - position);
            } catch (SignatureException e) {
                throw new RuntimeException(e); //Wrap SignatureException
            }
            input.position(limit);
        } else {
            tmp = new byte[input.limit() - input.position()];
            input.get(tmp);
            try {
                engineUpdate(tmp, 0, tmp.length);
            } catch (SignatureException e) {
                throw new RuntimeException(e); //Wrap SignatureException
            }
        }
    }

    /**
     * Generates and returns the signature of all updated data.
     * <p>
     * This {@code SignatureSpi} instance is reset to the state of its last
     * initialization for signing and thus can be used for another signature
     * from the same identity.
     *
     * @return the signature of all updated data.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     */
    protected abstract byte[] engineSign() throws SignatureException;

    /**
     * Generates and stores the signature of all updated data in the provided
     * {@code byte[]} at the specified position with the specified length.
     * <p>
     * This {@code SignatureSpi} instance is reset to the state of its last
     * initialization for signing and thus can be used for another signature
     * from the same identity.
     *
     * @param outbuf
     *            the buffer to store the signature.
     * @param offset
     *            the index of the first byte in {@code outbuf} to store.
     * @param len
     *            the number of bytes allocated for the signature.
     * @return the number of bytes stored in {@code outbuf}.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     * @throws IllegalArgumentException
     *             if {@code offset} or {@code len} are not valid in respect to
     *             {@code outbuf}.
     */
    protected int engineSign(byte[] outbuf, int offset, int len) throws SignatureException {
        byte[] tmp = engineSign();
        if (tmp == null) {
            return 0;
        }
        if (len < tmp.length) {
            throw new SignatureException("The value of len parameter is less than the actual signature length");
        }
        if (offset < 0) {
            throw new SignatureException("offset < 0");
        }
        if (offset + len > outbuf.length) {
            throw new SignatureException("offset + len > outbuf.length");
        }
        System.arraycopy(tmp, 0, outbuf, offset, tmp.length);
        return tmp.length;
    }

    /**
     * Indicates whether the given {@code sigBytes} can be verified using the
     * public key or a certificate of the signer.
     * <p>
     * This {@code SignatureSpi} instance is reset to the state of its last
     * initialization for verifying and thus can be used to verify another
     * signature of the same signer.
     *
     * @param sigBytes
     *            the signature to verify.
     * @return {@code true} if the signature was verified, {@code false}
     *         otherwise.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     */
    protected abstract boolean engineVerify(byte[] sigBytes)
            throws SignatureException;

    /**
     * Indicates whether the given {@code sigBytes} starting at index {@code
     * offset} with {@code length} bytes can be verified using the public key or
     * a certificate of the signer.
     * <p>
     * This {@code SignatureSpi} instance is reset to the state of its last
     * initialization for verifying and thus can be used to verify another
     * signature of the same signer.
     *
     * @param sigBytes
     *            the {@code byte[]} containing the signature to verify.
     * @param offset
     *            the start index in {@code sigBytes} of the signature
     * @param length
     *            the number of bytes allocated for the signature.
     * @return {@code true} if the signature was verified, {@code false}
     *         otherwise.
     * @throws SignatureException
     *             if this {@code SignatureSpi} instance is not initialized
     *             properly.
     * @throws IllegalArgumentException
     *             if {@code offset} or {@code length} are not valid in respect
     *             to {@code sigBytes}.
     */
    protected boolean engineVerify(byte[] sigBytes, int offset, int length)
            throws SignatureException {
        byte[] tmp = new byte[length];
        System.arraycopy(sigBytes, offset, tmp, 0, length);
        return engineVerify(tmp);
    }

    /**
     * Sets the specified parameter to the given value.
     *
     * @param param
     *            the name of the parameter.
     * @param value
     *            the parameter value.
     * @throws InvalidParameterException
     *             if the parameter is invalid, already set or is not allowed to
     *             be changed.
     * @deprecated Use {@link #engineSetParameter(AlgorithmParameterSpec)}
     */
    @Deprecated
    protected abstract void engineSetParameter(String param, Object value)
            throws InvalidParameterException;

    /**
     * Sets the specified {@code AlgorithmParameterSpec}.
     *
     * @param params
     *            the parameter to set.
     * @throws InvalidAlgorithmParameterException
     *             if the parameter is invalid, already set or is not allowed to
     *             be changed.
     */
    protected void engineSetParameter(AlgorithmParameterSpec params)
            throws InvalidAlgorithmParameterException {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the {@code AlgorithmParameters} of this {@link SignatureSpi}
     * instance.
     *
     * @return the {@code AlgorithmParameters} of this {@link SignatureSpi}
     *         instance, maybe {@code null}.
     */
    protected AlgorithmParameters engineGetParameters() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the value of the parameter with the specified name.
     *
     * @param param
     *            the name of the requested parameter value.
     * @return the value of the parameter with the specified name, maybe {@code
     *         null}.
     * @throws InvalidParameterException
     *             if {@code param} is not a valid parameter for this {@code
     *             SignatureSpi} or an other error occurs.
     * @deprecated There is no generally accepted parameter naming convention.
     */
    @Deprecated
    protected abstract Object engineGetParameter(String param)
            throws InvalidParameterException;

    @Override
    public Object clone() throws CloneNotSupportedException {
        if (this instanceof Cloneable) {
            return super.clone();
        }
        throw new CloneNotSupportedException();
    }
}
