/*
 * Copyright (c) 2024, 2025, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.crypto;

import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

/**
 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
 * Key Derivation Function ({@link KDF}) class.
 * <p>
 * All the abstract methods in this class must be implemented by each
 * cryptographic service provider who wishes to supply the implementation of a
 * particular key derivation function algorithm.
 * <p>
 * Implementations must provide a public constructor which accepts a {@code
 * KDFParameters} object if they depend on the default implementation of
 * {@code Provider.Service.newInstance} to construct {@code KDFSpi} instances.
 * The constructor must call {@code super(params)} passing the parameters
 * supplied. The constructor must also throw an
 * {@code InvalidAlgorithmParameterException} if the supplied parameters are
 * inappropriate. If a {@code KDF} object is instantiated with one of the
 * {@code getInstance} methods that contains a {@code KDFParameters} parameter,
 * the user-provided {@code KDFParameters} object will be passed to the
 * constructor of the {@code KDFSpi} implementation. Otherwise, if it is
 * instantiated with one of the {@code getInstance} methods without a
 * {@code KDFParameters} parameter, a {@code null} value will be passed to the
 * constructor.
 * <p>
 * Implementations which do not support {@code KDFParameters} must require
 * {@code null} to be passed, otherwise an
 * {@code InvalidAlgorithmParameterException} will be thrown. On the other hand,
 * implementations which require {@code KDFParameters} should throw an
 * {@code InvalidAlgorithmParameterException} upon receiving a {@code null}
 * value if default parameters cannot be generated or upon receiving {@code
 * KDFParameters} which are not supported by the implementation.
 * <p>
 * To aid the caller, implementations may return parameters with additional
 * default values or supply random values as used by the underlying {@code KDF}
 * algorithm. See {@link KDFSpi#engineGetParameters()} for more details.
 *
 * @see KDF
 * @see KDFParameters
 * @see KDF#getParameters()
 * @see SecretKey
 * @since 25
 */
public abstract class KDFSpi {

    /**
     * The sole constructor.
     * <p>
     * A {@code KDFParameters} object may be specified for KDF algorithms that
     * support initialization parameters.
     *
     * @param kdfParameters
     *         the initialization parameters for the {@code KDF} algorithm (may
     *         be {@code null})
     *
     * @throws InvalidAlgorithmParameterException
     *         if the initialization parameters are inappropriate for this
     *         {@code KDFSpi}
     * @see KDF#getParameters()
     */
    protected KDFSpi(KDFParameters kdfParameters)
            throws InvalidAlgorithmParameterException {}

    /**
     * Returns the {@code KDFParameters} used with this {@code KDF} object.
     * <p>
     * The returned parameters may be the same that were used to initialize
     * this {@code KDF} object, or may contain additional default or
     * random parameter values used by the underlying KDF algorithm.
     * If the required parameters were not supplied and can be generated by
     * the {@code KDF} object, the generated parameters are returned;
     * otherwise {@code null} is returned.
     *
     * @return the parameters used with this {@code KDF} object, or
     *         {@code null}
     */
    protected abstract KDFParameters engineGetParameters();

    /**
     * Derives a key, returned as a {@code SecretKey} object.
     *
     * @implNote If the resultant key is extractable, then its
     *         {@code getEncoded} value should have the same content as the
     *         result of {@code deriveData}.
     *
     * @param alg
     *         the algorithm of the resultant {@code SecretKey} object.
     *         See the SecretKey Algorithms section in the
     *         <a href="{@docRoot}/../specs/security/standard-names.html#secretkey-algorithms">
     *         Java Security Standard Algorithm Names Specification</a>
     *         for information about standard secret key algorithm names.
     * @param derivationSpec
     *         derivation parameters
     *
     * @return the derived key.
     *
     * @throws InvalidAlgorithmParameterException
     *         if the information contained within the {@code derivationSpec} is
     *         invalid or if the combination of {@code alg} and the
     *         {@code derivationSpec} results in something invalid
     * @throws NoSuchAlgorithmException
     *         if {@code alg} is empty or invalid
     * @throws NullPointerException
     *         if {@code alg} or {@code derivationSpec} is null
     * @spec security/standard-names.html Java Security Standard Algorithm Names
     */
    protected abstract SecretKey engineDeriveKey(String alg,
                                                 AlgorithmParameterSpec derivationSpec)
            throws InvalidAlgorithmParameterException, NoSuchAlgorithmException;

    /**
     * Derives a key, returns raw data as a byte array.
     *
     * @param derivationSpec
     *         derivation parameters
     *
     * @return the derived key in its raw bytes.
     *
     * @throws InvalidAlgorithmParameterException
     *         if the information contained within the {@code derivationSpec} is
     *         invalid
     * @throws UnsupportedOperationException
     *         if the derived keying material is not extractable
     * @throws NullPointerException
     *         if {@code derivationSpec} is null
     */
    protected abstract byte[] engineDeriveData(
            AlgorithmParameterSpec derivationSpec)
            throws InvalidAlgorithmParameterException;

}
