// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.jcajce.provider.asymmetric.mlkem;

import org.bouncycastle.jcajce.util.SpecUtil;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMPublicKeyParameters;
import java.security.KeyPair;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import java.security.spec.AlgorithmParameterSpec;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.util.Strings;
import org.bouncycastle.jcajce.spec.MLKEMParameterSpec;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMParameters;
import java.security.SecureRandom;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMKeyPairGenerator;
import org.bouncycastle.pqc.crypto.mlkem.MLKEMKeyGenerationParameters;
import java.security.KeyPairGenerator;

public class MLKEMKeyPairGeneratorSpi extends KeyPairGenerator
{
    MLKEMKeyGenerationParameters param;
    MLKEMKeyPairGenerator engine;
    SecureRandom random;
    boolean initialised;
    private MLKEMParameters mlkemParameters;
    
    public MLKEMKeyPairGeneratorSpi() {
        super("ML-KEM");
        this.engine = new MLKEMKeyPairGenerator();
        this.random = CryptoServicesRegistrar.getSecureRandom();
        this.initialised = false;
    }
    
    protected MLKEMKeyPairGeneratorSpi(final MLKEMParameterSpec mlkemParameterSpec) {
        super(Strings.toUpperCase(mlkemParameterSpec.getName()));
        this.engine = new MLKEMKeyPairGenerator();
        this.random = CryptoServicesRegistrar.getSecureRandom();
        this.initialised = false;
        this.mlkemParameters = Utils.getParameters(mlkemParameterSpec.getName());
        if (this.param == null) {
            this.param = new MLKEMKeyGenerationParameters(this.random, this.mlkemParameters);
        }
        this.engine.init(this.param);
        this.initialised = true;
    }
    
    @Override
    public void initialize(final int n, final SecureRandom secureRandom) {
        throw new IllegalArgumentException("use AlgorithmParameterSpec");
    }
    
    @Override
    public void initialize(final AlgorithmParameterSpec algorithmParameterSpec) throws InvalidAlgorithmParameterException {
        try {
            this.initialize(algorithmParameterSpec, new BCJcaJceHelper().createSecureRandom("DEFAULT"));
        }
        catch (final NoSuchAlgorithmException ex) {
            throw new IllegalStateException("unable to find DEFAULT DRBG");
        }
    }
    
    @Override
    public void initialize(final AlgorithmParameterSpec obj, final SecureRandom secureRandom) throws InvalidAlgorithmParameterException {
        final String nameFromParams = getNameFromParams(obj);
        if (nameFromParams == null) {
            throw new InvalidAlgorithmParameterException("invalid ParameterSpec: " + obj);
        }
        final MLKEMParameters parameters = Utils.getParameters(nameFromParams);
        if (parameters == null) {
            throw new InvalidAlgorithmParameterException("unknown parameter set name: " + nameFromParams);
        }
        if (this.mlkemParameters != null && !parameters.getName().equals(this.mlkemParameters.getName())) {
            throw new InvalidAlgorithmParameterException("key pair generator locked to " + this.getAlgorithm());
        }
        this.param = new MLKEMKeyGenerationParameters(secureRandom, parameters);
        this.engine.init(this.param);
        this.initialised = true;
    }
    
    @Override
    public KeyPair generateKeyPair() {
        if (!this.initialised) {
            this.param = new MLKEMKeyGenerationParameters(this.random, MLKEMParameters.ml_kem_768);
            this.engine.init(this.param);
            this.initialised = true;
        }
        final AsymmetricCipherKeyPair generateKeyPair = this.engine.generateKeyPair();
        return new KeyPair(new BCMLKEMPublicKey((MLKEMPublicKeyParameters)generateKeyPair.getPublic()), new BCMLKEMPrivateKey((MLKEMPrivateKeyParameters)generateKeyPair.getPrivate()));
    }
    
    private static String getNameFromParams(final AlgorithmParameterSpec algorithmParameterSpec) {
        if (algorithmParameterSpec instanceof MLKEMParameterSpec) {
            return ((MLKEMParameterSpec)algorithmParameterSpec).getName();
        }
        return Strings.toUpperCase(SpecUtil.getNameFrom(algorithmParameterSpec));
    }
    
    public static class MLKEM1024 extends MLKEMKeyPairGeneratorSpi
    {
        public MLKEM1024() {
            super(MLKEMParameterSpec.ml_kem_1024);
        }
    }
    
    public static class MLKEM512 extends MLKEMKeyPairGeneratorSpi
    {
        public MLKEM512() {
            super(MLKEMParameterSpec.ml_kem_512);
        }
    }
    
    public static class MLKEM768 extends MLKEMKeyPairGeneratorSpi
    {
        public MLKEM768() {
            super(MLKEMParameterSpec.ml_kem_768);
        }
    }
}
