/*
 * Copyright (c) 2023, 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.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

/**
 * This class defines the Service Provider Interface (SPI) for the {@link KEM}
 * class. A security provider implements this interface to provide an
 * implementation of a Key Encapsulation Mechanism (KEM) algorithm.
 * <p>
 * A KEM algorithm may support a family of configurations. Each configuration
 * may accept different types of keys, cryptographic primitives, and sizes of
 * shared secrets and key encapsulation messages. A configuration is defined
 * by the KEM algorithm name, the key it uses, and an optional
 * {@code AlgorithmParameterSpec} argument that is specified when creating
 * an encapsulator or decapsulator. The result of calling
 * {@link #engineNewEncapsulator} or {@link #engineNewDecapsulator} must return
 * an encapsulator or decapsulator that maps to a single configuration,
 * where its {@code engineSecretSize()} and {@code engineEncapsulationSize()}
 * methods return constant values.
 * <p>
 * A {@code KEMSpi} implementation must be immutable. It must be safe to
 * call multiple {@code engineNewEncapsulator} and {@code engineNewDecapsulator}
 * methods at the same time.
 * <p>
 * {@code EncapsulatorSpi} and {@code DecapsulatorSpi} implementations must also
 * be immutable. It must be safe to invoke multiple {@code encapsulate} and
 * {@code decapsulate} methods at the same time. Each invocation of
 * {@code encapsulate} should generate a new shared secret and key
 * encapsulation message.
 * <p>
 * For example,
 * {@snippet lang = java:
 * public static class MyKEMImpl implements KEMSpi {
 *
 *     @Override
 *     public KEMSpi.EncapsulatorSpi engineNewEncapsulator(PublicKey publicKey,
 *             AlgorithmParameterSpec spec, SecureRandom secureRandom)
 *             throws InvalidAlgorithmParameterException, InvalidKeyException {
 *         if (!checkPublicKey(publicKey)) {
 *             throw new InvalidKeyException("unsupported key");
 *         }
 *         if (!checkParameters(spec)) {
 *             throw new InvalidAlgorithmParameterException("unsupported params");
 *         }
 *         return new MyEncapsulator(publicKey, spec, secureRandom);
 *     }
 *
 *     class MyEncapsulator implements KEMSpi.EncapsulatorSpi {
 *         MyEncapsulator(PublicKey publicKey, AlgorithmParameterSpec spec,
 *                 SecureRandom secureRandom){
 *             this.spec = spec != null ? spec : getDefaultParameters();
 *             this.secureRandom = secureRandom != null
 *                     ? secureRandom
 *                     : getDefaultSecureRandom();
 *             this.publicKey = publicKey;
 *         }
 *
 *         @Override
 *         public KEM.Encapsulated encapsulate(int from, int to, String algorithm) {
 *             byte[] encapsulation;
 *             byte[] secret;
 *             // calculating...
 *             return new KEM.Encapsulated(
 *                     new SecretKeySpec(secret, from, to - from, algorithm),
 *                     encapsulation, null);
 *         }
 *
 *         // ...
 *     }
 *
 *     // ...
 * }
 * }
 *
 * @see KEM
 * @since 21
 */
public interface KEMSpi {

    /**
     * The KEM encapsulator implementation, generated by
     * {@link #engineNewEncapsulator} on the KEM sender side.
     *
     * @see KEM.Encapsulator
     *
     * @since 21
     */
    interface EncapsulatorSpi {
        /**
         * The key encapsulation function.
         * <p>
         * Each invocation of this method must generate a new secret key and key
         * encapsulation message that is returned in an {@link KEM.Encapsulated} object.
         * <p>
         * An implementation must support the case where {@code from} is 0,
         * {@code to} is the same as the return value of {@code secretSize()},
         * and {@code algorithm} is "Generic".
         *
         * @param from the initial index of the shared secret byte array
         *          to be returned, inclusive
         * @param to the final index of the shared secret byte array
         *          to be returned, exclusive
         * @param algorithm the algorithm name for the secret key that is returned.
         *          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.
         *          Specify "Generic" if the output will be used as the input keying
         *          material of a key derivation function (KDF).
         * @return an {@link KEM.Encapsulated} object containing a portion of
         *          the shared secret as a key with the specified algorithm,
         *          key encapsulation message, and optional parameters.
         * @throws IndexOutOfBoundsException if {@code from < 0},
         *     {@code from > to}, or {@code to > secretSize()}
         * @throws NullPointerException if {@code algorithm} is {@code null}
         * @throws UnsupportedOperationException if the combination of
         *          {@code from}, {@code to}, and {@code algorithm}
         *          is not supported by the encapsulator
         * @see KEM.Encapsulated
         * @see KEM.Encapsulator#encapsulate(int, int, String)
         * @spec security/standard-names.html Java Security Standard Algorithm Names
         */
        KEM.Encapsulated engineEncapsulate(int from, int to, String algorithm);

        /**
         * Returns the size of the shared secret.
         *
         * @return the size of the shared secret as a finite non-negative integer
         * @see KEM.Encapsulator#secretSize()
         */
        int engineSecretSize();

        /**
         * Returns the size of the key encapsulation message.
         *
         * @return the size of the key encapsulation message as a finite non-negative integer
         * @see KEM.Encapsulator#encapsulationSize()
         */
        int engineEncapsulationSize();
    }

    /**
     * The KEM decapsulator implementation, generated by
     * {@link #engineNewDecapsulator} on the KEM receiver side.
     *
     * @see KEM.Decapsulator
     *
     * @since 21
     */
    interface DecapsulatorSpi {
        /**
         * The key decapsulation function.
         * <p>
         * An invocation of this method recovers the secret key from the key
         * encapsulation message.
         * <p>
         * An implementation must support the case where {@code from} is 0,
         * {@code to} is the same as the return value of {@code secretSize()},
         * and {@code algorithm} is "Generic".
         *
         * @param encapsulation the key encapsulation message from the sender.
         *          The size must be equal to the value returned by
         *          {@link #engineEncapsulationSize()} ()}, or a
         *          {@code DecapsulateException} must be thrown.
         * @param from the initial index of the shared secret byte array
         *          to be returned, inclusive
         * @param to the final index of the shared secret byte array
         *          to be returned, exclusive
         * @param algorithm the algorithm name for the secret key that is returned.
         *          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.
         *          Specify "Generic" if the output will be used as the input keying
         *          material of a key derivation function (KDF).
         * @return a portion of the shared secret as a {@code SecretKey} with
         *          the specified algorithm
         * @throws DecapsulateException if an error occurs during the
         *          decapsulation process
         * @throws IndexOutOfBoundsException if {@code from < 0},
         *          {@code from > to}, or {@code to > secretSize()}
         * @throws NullPointerException if {@code encapsulation} or
         *          {@code algorithm} is {@code null}
         * @throws UnsupportedOperationException if the combination of
         *          {@code from}, {@code to}, and {@code algorithm}
         *          is not supported by the decapsulator
         * @see KEM.Decapsulator#decapsulate(byte[], int, int, String)
         * @spec security/standard-names.html Java Security Standard Algorithm Names
         */
        SecretKey engineDecapsulate(byte[] encapsulation, int from, int to, String algorithm)
                throws DecapsulateException;

        /**
         * Returns the size of the shared secret.
         *
         * @return the size of the shared secret as a finite non-negative integer
         * @see KEM.Decapsulator#secretSize()
         */
        int engineSecretSize();

        /**
         * Returns the size of the key encapsulation message.
         *
         * @return the size of the key encapsulation message as a finite non-negative integer
         * @see KEM.Decapsulator#encapsulationSize()
         */
        int engineEncapsulationSize();
    }

    /**
     * Creates a KEM encapsulator on the KEM sender side.
     *
     * @param publicKey the receiver's public key, must not be {@code null}
     * @param spec the optional parameter, can be {@code null}
     * @param secureRandom the source of randomness for encapsulation.
     *                     If {@code null}, the implementation must provide
     *                     a default one.
     * @return the encapsulator for this key
     * @throws InvalidAlgorithmParameterException if {@code spec} is invalid
     *          or one is required but {@code spec} is {@code null}
     * @throws InvalidKeyException if {@code publicKey} is {@code null} or invalid
     * @see KEM#newEncapsulator(PublicKey, AlgorithmParameterSpec, SecureRandom)
     */
    EncapsulatorSpi engineNewEncapsulator(PublicKey publicKey,
            AlgorithmParameterSpec spec, SecureRandom secureRandom)
            throws InvalidAlgorithmParameterException, InvalidKeyException;

    /**
     * Creates a KEM decapsulator on the KEM receiver side.
     *
     * @param privateKey the receiver's private key, must not be {@code null}
     * @param spec the optional parameter, can be {@code null}
     * @return the decapsulator for this key
     * @throws InvalidAlgorithmParameterException if {@code spec} is invalid
     *          or one is required but {@code spec} is {@code null}
     * @throws InvalidKeyException if {@code privateKey} is {@code null} or invalid
     * @see KEM#newDecapsulator(PrivateKey, AlgorithmParameterSpec)
     */
    DecapsulatorSpi engineNewDecapsulator(PrivateKey privateKey, AlgorithmParameterSpec spec)
            throws InvalidAlgorithmParameterException, InvalidKeyException;
}
