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

package org.bouncycastle.crypto.digests;

import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.engines.AsconPermutationFriend;

abstract class AsconBaseDigest extends BufferBaseDigest
{
    AsconPermutationFriend.AsconPermutation p;
    protected int ASCON_PB_ROUNDS;
    
    protected AsconBaseDigest() {
        super(ProcessingBufferType.Immediate, 8);
        this.ASCON_PB_ROUNDS = 12;
        this.p = AsconPermutationFriend.getAsconPermutation(ISAPDigest.Friend.getFriend(Friend.INSTANCE));
        this.DigestSize = 32;
    }
    
    protected abstract long pad(final int p0);
    
    protected abstract long loadBytes(final byte[] p0, final int p1);
    
    protected abstract long loadBytes(final byte[] p0, final int p1, final int p2);
    
    protected abstract void setBytes(final long p0, final byte[] p1, final int p2);
    
    protected abstract void setBytes(final long p0, final byte[] p1, final int p2, final int p3);
    
    @Override
    protected void processBytes(final byte[] array, final int n) {
        final AsconPermutationFriend.AsconPermutation p2 = this.p;
        p2.x0 ^= this.loadBytes(array, n);
        this.p.p(this.ASCON_PB_ROUNDS);
    }
    
    @Override
    protected void finish(final byte[] array, final int n) {
        this.padAndAbsorb();
        this.squeeze(array, n, this.DigestSize);
    }
    
    protected void padAndAbsorb() {
        final AsconPermutationFriend.AsconPermutation p = this.p;
        p.x0 ^= (this.loadBytes(this.m_buf, 0, this.m_bufPos) ^ this.pad(this.m_bufPos));
        this.p.p(12);
    }
    
    protected void squeeze(final byte[] array, int n, int i) {
        while (i > this.BlockSize) {
            this.setBytes(this.p.x0, array, n);
            this.p.p(this.ASCON_PB_ROUNDS);
            n += this.BlockSize;
            i -= this.BlockSize;
        }
        this.setBytes(this.p.x0, array, n, i);
    }
    
    protected int hash(final byte[] array, final int n, final int n2) {
        this.ensureSufficientOutputBuffer(array, n, n2);
        this.padAndAbsorb();
        this.squeeze(array, n, n2);
        return n2;
    }
    
    protected void ensureSufficientOutputBuffer(final byte[] array, final int n, final int n2) {
        if (n + n2 > array.length) {
            throw new OutputLengthException("output buffer is too short");
        }
    }
    
    public static class Friend
    {
        private static final Friend INSTANCE;
        
        private Friend() {
        }
        
        static {
            INSTANCE = new Friend();
        }
    }
}
