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

package org.bouncycastle.jcajce.provider.symmetric.util;

import java.security.InvalidAlgorithmParameterException;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import java.security.spec.InvalidParameterSpecException;
import org.bouncycastle.util.Integers;
import org.bouncycastle.internal.asn1.cms.GCMParameters;
import org.bouncycastle.asn1.ASN1Primitive;
import java.security.spec.AlgorithmParameterSpec;
import java.security.PrivilegedActionException;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;

public class GcmSpecUtil
{
    static final Class gcmSpecClass;
    private static final Constructor constructor;
    private static final Method tLen;
    private static final Method iv;
    
    private static Constructor extractConstructor() {
        try {
            return AccessController.doPrivileged((PrivilegedExceptionAction<Constructor>)new PrivilegedExceptionAction() {
                @Override
                public Object run() throws Exception {
                    return GcmSpecUtil.gcmSpecClass.getConstructor(Integer.TYPE, byte[].class);
                }
            });
        }
        catch (final PrivilegedActionException ex) {
            return null;
        }
    }
    
    private static Method extractMethod(final String s) {
        try {
            return AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction() {
                @Override
                public Object run() throws Exception {
                    return GcmSpecUtil.gcmSpecClass.getDeclaredMethod(s, (Class[])new Class[0]);
                }
            });
        }
        catch (final PrivilegedActionException ex) {
            return null;
        }
    }
    
    public static boolean gcmSpecExists() {
        return GcmSpecUtil.gcmSpecClass != null;
    }
    
    public static boolean gcmSpecExtractable() {
        return GcmSpecUtil.constructor != null;
    }
    
    public static boolean isGcmSpec(final AlgorithmParameterSpec algorithmParameterSpec) {
        return GcmSpecUtil.gcmSpecClass != null && GcmSpecUtil.gcmSpecClass.isInstance(algorithmParameterSpec);
    }
    
    public static boolean isGcmSpec(final Class clazz) {
        return GcmSpecUtil.gcmSpecClass == clazz;
    }
    
    public static AlgorithmParameterSpec extractGcmSpec(final ASN1Primitive asn1Primitive) throws InvalidParameterSpecException {
        try {
            final GCMParameters instance = GCMParameters.getInstance(asn1Primitive);
            return (AlgorithmParameterSpec)GcmSpecUtil.constructor.newInstance(Integers.valueOf(instance.getIcvLen() * 8), instance.getNonce());
        }
        catch (final Exception ex) {
            throw new InvalidParameterSpecException("Construction failed: " + ex.getMessage());
        }
    }
    
    static AEADParameters extractAeadParameters(final KeyParameter keyParameter, final AlgorithmParameterSpec algorithmParameterSpec) throws InvalidAlgorithmParameterException {
        try {
            return AccessController.doPrivileged((PrivilegedExceptionAction<AEADParameters>)new PrivilegedExceptionAction() {
                @Override
                public Object run() throws Exception {
                    return new AEADParameters(keyParameter, (int)GcmSpecUtil.tLen.invoke(algorithmParameterSpec, new Object[0]), (byte[])GcmSpecUtil.iv.invoke(algorithmParameterSpec, new Object[0]));
                }
            });
        }
        catch (final Exception ex) {
            throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec.");
        }
    }
    
    public static GCMParameters extractGcmParameters(final AlgorithmParameterSpec algorithmParameterSpec) throws InvalidParameterSpecException {
        try {
            return AccessController.doPrivileged((PrivilegedExceptionAction<GCMParameters>)new PrivilegedExceptionAction() {
                @Override
                public Object run() throws Exception {
                    return new GCMParameters((byte[])GcmSpecUtil.iv.invoke(algorithmParameterSpec, new Object[0]), (int)GcmSpecUtil.tLen.invoke(algorithmParameterSpec, new Object[0]) / 8);
                }
            });
        }
        catch (final Exception ex) {
            throw new InvalidParameterSpecException("Cannot process GCMParameterSpec");
        }
    }
    
    static {
        gcmSpecClass = ClassUtil.loadClass(GcmSpecUtil.class, "javax.crypto.spec.GCMParameterSpec");
        if (GcmSpecUtil.gcmSpecClass != null) {
            constructor = extractConstructor();
            tLen = extractMethod("getTLen");
            iv = extractMethod("getIV");
        }
        else {
            constructor = null;
            tLen = null;
            iv = null;
        }
    }
}
