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

package org.bouncycastle.pqc.crypto.snova;

import java.util.HashMap;
import org.bouncycastle.crypto.modes.CTRModeCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.modes.SICBlockCipher;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.util.Pack;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.GF16;
import org.bouncycastle.crypto.digests.SHAKEDigest;
import org.bouncycastle.util.Integers;
import java.util.Map;

class SnovaEngine
{
    private static final Map<Integer, byte[]> fixedAbqSet;
    private static final Map<Integer, byte[][]> sSet;
    private static final Map<Integer, int[][]> xSSet;
    private final SnovaParameters params;
    private final int l;
    private final int lsq;
    private final int m;
    private final int v;
    private final int o;
    private final int alpha;
    private final int n;
    final byte[][] S;
    final int[][] xS;
    
    public SnovaEngine(final SnovaParameters params) {
        this.params = params;
        this.l = params.getL();
        this.lsq = params.getLsq();
        this.m = params.getM();
        this.v = params.getV();
        this.o = params.getO();
        this.alpha = params.getAlpha();
        this.n = params.getN();
        if (!SnovaEngine.xSSet.containsKey(Integers.valueOf(this.l))) {
            final byte[][] array = new byte[this.l][this.lsq];
            final int[][] array2 = new int[this.l][this.lsq];
            this.be_aI(array[0], 0, (byte)1);
            this.beTheS(array[1]);
            for (int i = 2; i < this.l; ++i) {
                GF16Utils.gf16mMul(array[i - 1], array[1], array[i], this.l);
            }
            for (int j = 0; j < this.l; ++j) {
                for (int k = 0; k < this.lsq; ++k) {
                    array2[j][k] = GF16Utils.gf16FromNibble(array[j][k]);
                }
            }
            SnovaEngine.sSet.put(Integers.valueOf(this.l), array);
            SnovaEngine.xSSet.put(Integers.valueOf(this.l), array2);
        }
        this.S = SnovaEngine.sSet.get(Integers.valueOf(this.l));
        this.xS = SnovaEngine.xSSet.get(Integers.valueOf(this.l));
        if (this.l < 4 && !SnovaEngine.fixedAbqSet.containsKey(Integers.valueOf(this.o))) {
            final int n = this.alpha * this.l;
            final int n2 = n * this.l;
            final int n3 = this.o * n;
            final int n4 = this.o * n2;
            final byte[] array3 = new byte[n4 << 2];
            final byte[] array4 = new byte[n4 + n3];
            final byte[] array5 = new byte[n3 << 2];
            final byte[] bytes = "SNOVA_ABQ".getBytes();
            final SHAKEDigest shakeDigest = new SHAKEDigest(256);
            shakeDigest.update(bytes, 0, bytes.length);
            shakeDigest.doFinal(array4, 0, array4.length);
            GF16.decode(array4, array3, n4 << 1);
            GF16.decode(array4, n2, array5, 0, n3 << 1);
            for (int l = 0, n5 = 0, n6 = 0; l < this.o; ++l, n5 += n2, n6 += n) {
                for (int n7 = 0, n8 = n6, n9 = n5; n7 < this.alpha; ++n7, n8 += this.l, n9 += this.lsq) {
                    this.makeInvertibleByAddingAS(array3, n9);
                    this.makeInvertibleByAddingAS(array3, n4 + n9);
                    this.genAFqS(array5, n8, array3, (n4 << 1) + n9);
                    this.genAFqS(array5, n3 + n8, array3, (n4 << 1) + n4 + n9);
                }
            }
            SnovaEngine.fixedAbqSet.put(Integers.valueOf(this.o), array3);
        }
    }
    
    private void beTheS(final byte[] array) {
        for (int i = 0, n = 0; i < this.l; ++i, n += this.l) {
            for (int j = 0; j < this.l; ++j) {
                array[n + j] = (byte)(8 - (i + j) & 0xF);
            }
        }
        if (this.l == 5) {
            array[24] = 9;
        }
    }
    
    private void be_aI(final byte[] array, int n, final byte b) {
        for (int n2 = this.l + 1, i = 0; i < this.l; ++i, n += n2) {
            array[n] = b;
        }
    }
    
    private void genAFqSCT(final byte[] array, final int n, final byte[] array2) {
        final int[] array3 = new int[this.lsq];
        final int n2 = this.l + 1;
        final int gf16FromNibble = GF16Utils.gf16FromNibble(array[n]);
        for (int i = 0, n3 = 0; i < this.l; ++i, n3 += n2) {
            array3[n3] = gf16FromNibble;
        }
        for (int j = 1; j < this.l - 1; ++j) {
            final int gf16FromNibble2 = GF16Utils.gf16FromNibble(array[n + j]);
            for (int k = 0; k < this.lsq; ++k) {
                final int[] array4 = array3;
                final int n4 = k;
                array4[n4] ^= gf16FromNibble2 * this.xS[j][k];
            }
        }
        final int ctGF16IsNotZero = GF16Utils.ctGF16IsNotZero(array[n + this.l - 1]);
        final int gf16FromNibble3 = GF16Utils.gf16FromNibble((byte)(ctGF16IsNotZero * array[n + this.l - 1] + (1 - ctGF16IsNotZero) * (15 + GF16Utils.ctGF16IsNotZero(array[n]) - array[n])));
        for (int l = 0; l < this.lsq; ++l) {
            final int[] array5 = array3;
            final int n5 = l;
            array5[n5] ^= gf16FromNibble3 * this.xS[this.l - 1][l];
            array2[l] = GF16Utils.gf16ToNibble(array3[l]);
        }
        Arrays.fill(array3, 0);
    }
    
    private void makeInvertibleByAddingAS(final byte[] array, final int n) {
        if (this.gf16Determinant(array, n) != 0) {
            return;
        }
        for (int i = 1; i < 16; ++i) {
            this.generateASMatrixTo(array, n, (byte)i);
            if (this.gf16Determinant(array, n) != 0) {
                return;
            }
        }
    }
    
    private byte gf16Determinant(final byte[] array, final int n) {
        switch (this.l) {
            case 2: {
                return this.determinant2x2(array, n);
            }
            case 3: {
                return this.determinant3x3(array, n);
            }
            case 4: {
                return this.determinant4x4(array, n);
            }
            case 5: {
                return this.determinant5x5(array, n);
            }
            default: {
                throw new IllegalStateException();
            }
        }
    }
    
    private byte determinant2x2(final byte[] array, final int n) {
        return (byte)(GF16.mul(array[n], array[n + 3]) ^ GF16.mul(array[n + 1], array[n + 2]));
    }
    
    private byte determinant3x3(final byte[] array, int n) {
        final byte b = array[n++];
        final byte b2 = array[n++];
        final byte b3 = array[n++];
        final byte b4 = array[n++];
        final byte b5 = array[n++];
        final byte b6 = array[n++];
        final byte b7 = array[n++];
        final byte b8 = array[n++];
        final byte b9 = array[n];
        return (byte)(GF16.mul(b, GF16.mul(b5, b9) ^ GF16.mul(b6, b8)) ^ GF16.mul(b2, GF16.mul(b4, b9) ^ GF16.mul(b6, b7)) ^ GF16.mul(b3, GF16.mul(b4, b8) ^ GF16.mul(b5, b7)));
    }
    
    private byte determinant4x4(final byte[] array, int n) {
        final byte b = array[n++];
        final byte b2 = array[n++];
        final byte b3 = array[n++];
        final byte b4 = array[n++];
        final byte b5 = array[n++];
        final byte b6 = array[n++];
        final byte b7 = array[n++];
        final byte b8 = array[n++];
        final byte b9 = array[n++];
        final byte b10 = array[n++];
        final byte b11 = array[n++];
        final byte b12 = array[n++];
        final byte b13 = array[n++];
        final byte b14 = array[n++];
        final byte b15 = array[n++];
        final byte b16 = array[n];
        final byte b17 = (byte)(GF16.mul(b11, b16) ^ GF16.mul(b12, b15));
        final byte b18 = (byte)(GF16.mul(b10, b16) ^ GF16.mul(b12, b14));
        final byte b19 = (byte)(GF16.mul(b10, b15) ^ GF16.mul(b11, b14));
        final byte b20 = (byte)(GF16.mul(b9, b16) ^ GF16.mul(b12, b13));
        final byte b21 = (byte)(GF16.mul(b9, b15) ^ GF16.mul(b11, b13));
        final byte b22 = (byte)(GF16.mul(b9, b14) ^ GF16.mul(b10, b13));
        return (byte)(GF16.mul(b, GF16.mul(b6, b17) ^ GF16.mul(b7, b18) ^ GF16.mul(b8, b19)) ^ GF16.mul(b2, GF16.mul(b5, b17) ^ GF16.mul(b7, b20) ^ GF16.mul(b8, b21)) ^ GF16.mul(b3, GF16.mul(b5, b18) ^ GF16.mul(b6, b20) ^ GF16.mul(b8, b22)) ^ GF16.mul(b4, GF16.mul(b5, b19) ^ GF16.mul(b6, b21) ^ GF16.mul(b7, b22)));
    }
    
    private byte determinant5x5(final byte[] array, int n) {
        final byte b = array[n++];
        final byte b2 = array[n++];
        final byte b3 = array[n++];
        final byte b4 = array[n++];
        final byte b5 = array[n++];
        final byte b6 = array[n++];
        final byte b7 = array[n++];
        final byte b8 = array[n++];
        final byte b9 = array[n++];
        final byte b10 = array[n++];
        final byte b11 = array[n++];
        final byte b12 = array[n++];
        final byte b13 = array[n++];
        final byte b14 = array[n++];
        final byte b15 = array[n++];
        final byte b16 = array[n++];
        final byte b17 = array[n++];
        final byte b18 = array[n++];
        final byte b19 = array[n++];
        final byte b20 = array[n++];
        final byte b21 = array[n++];
        final byte b22 = array[n++];
        final byte b23 = array[n++];
        final byte b24 = array[n++];
        final byte b25 = array[n];
        final byte b26 = (byte)(GF16.mul(b6, b12) ^ GF16.mul(b7, b11));
        final byte b27 = (byte)(GF16.mul(b6, b13) ^ GF16.mul(b8, b11));
        final byte b28 = (byte)(GF16.mul(b6, b14) ^ GF16.mul(b9, b11));
        final byte b29 = (byte)(GF16.mul(b6, b15) ^ GF16.mul(b10, b11));
        final byte b30 = (byte)(GF16.mul(b7, b13) ^ GF16.mul(b8, b12));
        final byte b31 = (byte)(GF16.mul(b7, b14) ^ GF16.mul(b9, b12));
        final byte b32 = (byte)(GF16.mul(b7, b15) ^ GF16.mul(b10, b12));
        final byte b33 = (byte)(GF16.mul(b8, b14) ^ GF16.mul(b9, b13));
        final byte b34 = (byte)(GF16.mul(b8, b15) ^ GF16.mul(b10, b13));
        final byte b35 = (byte)(GF16.mul(b9, b15) ^ GF16.mul(b10, b14));
        return (byte)((byte)((byte)((byte)((byte)((byte)((byte)((byte)((byte)((byte)GF16.mul(GF16.mul(b, b30) ^ GF16.mul(b2, b27) ^ GF16.mul(b3, b26), GF16.mul(b19, b25) ^ GF16.mul(b20, b24)) ^ GF16.mul(GF16.mul(b, b31) ^ GF16.mul(b2, b28) ^ GF16.mul(b4, b26), GF16.mul(b18, b25) ^ GF16.mul(b20, b23))) ^ GF16.mul(GF16.mul(b, b32) ^ GF16.mul(b2, b29) ^ GF16.mul(b5, b26), GF16.mul(b18, b24) ^ GF16.mul(b19, b23))) ^ GF16.mul(GF16.mul(b, b33) ^ GF16.mul(b3, b28) ^ GF16.mul(b4, b27), GF16.mul(b17, b25) ^ GF16.mul(b20, b22))) ^ GF16.mul(GF16.mul(b, b34) ^ GF16.mul(b3, b29) ^ GF16.mul(b5, b27), GF16.mul(b17, b24) ^ GF16.mul(b19, b22))) ^ GF16.mul(GF16.mul(b, b35) ^ GF16.mul(b4, b29) ^ GF16.mul(b5, b28), GF16.mul(b17, b23) ^ GF16.mul(b18, b22))) ^ GF16.mul(GF16.mul(b2, b33) ^ GF16.mul(b3, b31) ^ GF16.mul(b4, b30), GF16.mul(b16, b25) ^ GF16.mul(b20, b21))) ^ GF16.mul(GF16.mul(b2, b34) ^ GF16.mul(b3, b32) ^ GF16.mul(b5, b30), GF16.mul(b16, b24) ^ GF16.mul(b19, b21))) ^ GF16.mul(GF16.mul(b2, b35) ^ GF16.mul(b4, b32) ^ GF16.mul(b5, b31), GF16.mul(b16, b23) ^ GF16.mul(b18, b21))) ^ GF16.mul(GF16.mul(b3, b35) ^ GF16.mul(b4, b34) ^ GF16.mul(b5, b33), GF16.mul(b16, b22) ^ GF16.mul(b17, b21)));
    }
    
    private void generateASMatrixTo(final byte[] array, final int n, final byte b) {
        for (int i = 0, n2 = n; i < this.l; ++i, n2 += this.l) {
            for (int j = 0; j < this.l; ++j) {
                byte b2 = (byte)(8 - (i + j));
                if (this.l == 5 && i == 4 && j == 4) {
                    b2 = 9;
                }
                final int n3 = n2 + j;
                array[n3] ^= GF16.mul(b2, b);
            }
        }
    }
    
    private void genAFqS(final byte[] array, final int n, final byte[] array2, final int n2) {
        this.be_aI(array2, n2, array[n]);
        for (int i = 1; i < this.l - 1; ++i) {
            this.gf16mScaleTo(this.S[i], array[n + i], array2, n2);
        }
        this.gf16mScaleTo(this.S[this.l - 1], (byte)((array[n + this.l - 1] != 0) ? array[n + this.l - 1] : (16 - (array[n] + ((array[n] == 0) ? 1 : 0)))), array2, n2);
    }
    
    private void gf16mScaleTo(final byte[] array, final byte b, final byte[] array2, final int n) {
        for (int i = 0, n2 = 0; i < this.l; ++i, n2 += this.l) {
            for (int j = 0; j < this.l; ++j) {
                final int n3 = n2 + j + n;
                array2[n3] ^= GF16.mul(array[n2 + j], b);
            }
        }
    }
    
    private void genF(final MapGroup2 mapGroup2, final MapGroup1 mapGroup3, final byte[][][] array) {
        copy4DMatrix(mapGroup3.p11, mapGroup2.f11, this.m, this.v, this.v, this.lsq);
        copy4DMatrix(mapGroup3.p12, mapGroup2.f12, this.m, this.v, this.o, this.lsq);
        copy4DMatrix(mapGroup3.p21, mapGroup2.f21, this.m, this.o, this.v, this.lsq);
        for (int i = 0; i < this.m; ++i) {
            for (int j = 0; j < this.v; ++j) {
                for (int k = 0; k < this.o; ++k) {
                    for (int l = 0; l < this.v; ++l) {
                        GF16Utils.gf16mMulToTo(mapGroup3.p11[i][j][l], array[l][k], mapGroup3.p11[i][l][j], mapGroup2.f12[i][j][k], mapGroup2.f21[i][k][j], this.l);
                    }
                }
            }
        }
    }
    
    private static void copy4DMatrix(final byte[][][][] array, final byte[][][][] array2, final int n, final int n2, final int n3, final int n4) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n2; ++j) {
                for (int k = 0; k < n3; ++k) {
                    System.arraycopy(array[i][j][k], 0, array2[i][j][k], 0, n4);
                }
            }
        }
    }
    
    public void genP22(final byte[] array, final int n, final byte[][][] array2, final byte[][][][] array3, final byte[][][][] array4) {
        final int n2 = this.o * this.lsq;
        final int n3 = n2 * this.o;
        final byte[] array5 = new byte[this.m * n3];
        for (int i = 0, n4 = 0; i < this.m; ++i, n4 += n3) {
            for (int j = 0, n5 = n4; j < this.o; ++j, n5 += n2) {
                for (int k = 0, n6 = n5; k < this.o; ++k, n6 += this.lsq) {
                    for (int l = 0; l < this.v; ++l) {
                        GF16Utils.gf16mMulTo(array2[l][j], array4[i][l][k], array3[i][j][l], array2[l][k], array5, n6, this.l);
                    }
                }
            }
        }
        GF16.encode(array5, array, n, array5.length);
    }
    
    private void genSeedsAndT12(final byte[][][] array, final byte[] array2) {
        final int n = this.v * this.o * this.l;
        final byte[] array3 = new byte[n + 1 >>> 1];
        final SHAKEDigest shakeDigest = new SHAKEDigest(256);
        shakeDigest.update(array2, 0, array2.length);
        shakeDigest.doFinal(array3, 0, array3.length);
        final byte[] array4 = new byte[n];
        GF16.decode(array3, array4, n);
        int n2 = 0;
        for (int i = 0; i < this.v; ++i) {
            for (int j = 0; j < this.o; ++j) {
                this.genAFqSCT(array4, n2, array[i][j]);
                n2 += this.l;
            }
        }
    }
    
    public void genABQP(final MapGroup1 mapGroup1, final byte[] array) {
        final int n = this.lsq * (2 * this.m * this.alpha + this.m * (this.n * this.n - this.m * this.m)) + this.l * 2 * this.m * this.alpha;
        final byte[] array2 = new byte[this.m * this.alpha * this.l << 1];
        final byte[] array3 = new byte[n + 1 >> 1];
        if (this.params.isPkExpandShake()) {
            long n2 = 0L;
            int n3 = 0;
            int i = array3.length;
            final byte[] array4 = new byte[8];
            final SHAKEDigest shakeDigest = new SHAKEDigest(128);
            while (i > 0) {
                shakeDigest.update(array, 0, array.length);
                Pack.longToLittleEndian(n2, array4, 0);
                shakeDigest.update(array4, 0, 8);
                final int min = Math.min(i, 168);
                shakeDigest.doFinal(array3, n3, min);
                n3 += min;
                i -= min;
                ++n2;
            }
        }
        else {
            final byte[] array5 = new byte[16];
            final CTRModeCipher instance = SICBlockCipher.newInstance(AESEngine.newInstance());
            instance.init(true, new ParametersWithIV(new KeyParameter(array), array5));
            final int blockSize = instance.getBlockSize();
            final byte[] array6 = new byte[blockSize];
            int n4;
            for (n4 = 0; n4 + blockSize <= array3.length; n4 += blockSize) {
                instance.processBlock(array6, 0, array3, n4);
            }
            if (n4 < array3.length) {
                instance.processBlock(array6, 0, array6, 0);
                System.arraycopy(array6, 0, array3, n4, array3.length - n4);
            }
        }
        if ((this.lsq & 0x1) == 0x0) {
            mapGroup1.decode(array3, n - array2.length >> 1, this.l >= 4);
        }
        else {
            final byte[] array7 = new byte[n - array2.length];
            GF16.decode(array3, array7, array7.length);
            mapGroup1.fill(array7, this.l >= 4);
        }
        if (this.l >= 4) {
            GF16.decode(array3, n - array2.length >> 1, array2, 0, array2.length);
            int n5 = 0;
            int n6 = this.m * this.alpha * this.l;
            for (int j = 0; j < this.m; ++j) {
                for (int k = 0; k < this.alpha; ++k) {
                    this.makeInvertibleByAddingAS(mapGroup1.aAlpha[j][k], 0);
                    this.makeInvertibleByAddingAS(mapGroup1.bAlpha[j][k], 0);
                    this.genAFqS(array2, n5, mapGroup1.qAlpha1[j][k], 0);
                    this.genAFqS(array2, n6, mapGroup1.qAlpha2[j][k], 0);
                    n5 += this.l;
                    n6 += this.l;
                }
            }
        }
        else {
            final int n7 = this.o * this.alpha * this.lsq;
            final byte[] array8 = SnovaEngine.fixedAbqSet.get(Integers.valueOf(this.o));
            MapGroup1.fillAlpha(array8, 0, mapGroup1.aAlpha, this.m * n7);
            MapGroup1.fillAlpha(array8, n7, mapGroup1.bAlpha, (this.m - 1) * n7);
            MapGroup1.fillAlpha(array8, n7 * 2, mapGroup1.qAlpha1, (this.m - 2) * n7);
            MapGroup1.fillAlpha(array8, n7 * 3, mapGroup1.qAlpha2, (this.m - 3) * n7);
        }
    }
    
    public void genMap1T12Map2(final SnovaKeyElements snovaKeyElements, final byte[] array, final byte[] array2) {
        this.genSeedsAndT12(snovaKeyElements.T12, array2);
        this.genABQP(snovaKeyElements.map1, array);
        this.genF(snovaKeyElements.map2, snovaKeyElements.map1, snovaKeyElements.T12);
    }
    
    static {
        fixedAbqSet = new HashMap<Integer, byte[]>();
        sSet = new HashMap<Integer, byte[][]>();
        xSSet = new HashMap<Integer, int[][]>();
    }
}
